2011-03-19 52 views
7

当我写的接口类在C++中,我选择以下任一2个选项做什么用的接口的析构函数

class Interface 
{ 
public: 
    virtual R1 f1(p11, p12 , ...) = 0; 
    ... 
    virtual Rn fn(pn1, pn2 , ...) = 0; 
    virtual ~Interface() {} 
} 

class Interface 
{ 
public: 
    virtual R1 f1(p11, p12 , ...) = 0; 
    ... 
    virtual Rn fn(pn1, pn2 , ...) = 0; 
    virtual ~Interface() = 0; 
} 
Interface::~Interface() {} 

第一个版本是短写
第二种是有吸引力在于该接口的所有功能是纯虚

是否有任何理由我应该更喜欢一种或另一种方法(或者可能是第三种方法)?
谢谢

回答

5

据我了解,使得虚函数纯虚的目的是迫使派生类要么为它提供实施或选择由明确Derived::f()Base::f()默认实现。

所以如果那是真的,那么制作虚拟析构器pure virtual的目的是什么?它是否强制派生类为Base::~Base()提供实现?派生类可以执行Base::~Base()吗?

这样,就意味着,第一个版本与virtual析构函数似乎足够几乎所有目的。毕竟,虚拟析构函数最常见的用途是客户端可以通过类型为Base*的指针正确地导出派生类的delete对象。

但是,如果你把所有功能Base虚拟只,虚拟化,并为他们提供实现(其实你已经提供),并在同一时间你想Base抽象类型,然后在具有一个Base虚拟析构函数是仅溶液

class Base 
{ 
public: 
    virtual void f() {}; //not pure virtual 
    virtual ~Base() = 0; //pure - makes Base abstract type! 
}; 

Base::~Base() {} //yes, you have to do this as well. 

Base *pBase = new Base(); // error - cannot create instance! 

希望有所帮助。

1

在第一种情况下,派生类可以选择是否实现析构函数。 在第二种情况下,必须重写纯虚拟析构函数,所以派生类被迫实现析构函数。

除非你有什么理由要强制这么做,否则我会选择第一种情况。

+2

错误。第二种情况不会强制析构函数被覆盖:http://ideone.com/aw3kV。此外,这句话“所以基类被迫实现析构函数”*对我来说没有意义。你能改述一下吗? – Nawaz 2011-03-19 11:16:44

+0

@Nawaz - 对不起,错字。我的意思是“派生”,而不是“基础”。它现在已经修复。必须在凌晨5点停止编写代码。 – 2011-03-20 18:24:35

2

对我来说,dtor不是界面的一部分。 fi()将在其他语言中具有类似物,而不是dtor。同样,你可以为fi()写前置条件和后置条件,但不能写dtor。这使得它只是一个C++疣,而第一种技术是处理它的最舒适的方式。

+3

无论疣是否存在,C++都会使析构函数成为界面的一部分。无论是虚拟还是虚拟,都可以确定客户端是否可以通过指针到基地有效地“删除”派生类的实例。有效的客户操作==界面。但是,不管它是否纯粹,都不是外部界面的一部分,除非纳瓦兹说,如果它是唯一的纯函数,并且使得课堂抽象化。 – 2011-03-19 11:31:41

+1

我同意,但问题是关于虚拟与纯虚拟,而不是虚拟与非虚拟。 – fizzer 2011-03-19 11:42:01

+0

好吧,我误解你的意思是,在C++中,dtor并不是界面的一部分。我同意这个问题,提供的选项之间的差异不是界面的一部分。 – 2011-03-19 12:09:49

1

好吧,发现了一个环节,因此认为我会提到它作为一个答案:

Are inline virtual functions really a non-sense?

我见过的编译器不如果没有非发出 任何v表内联函数 根本就存在(并且在一个 实现文件中定义,而不是在 头中)。他们会抛出错误 像缺少vtable-for-class-A或 类似的东西,你会被 弄得像地狱一样,就像我一样。

事实上,这是一个与 标准不符合的,但它发生如此考虑 把至少一个虚函数 没有在头(如果只有虚拟 析构函数),这样编译器 可以发出一个虚函数表在那个地方的 。我知道它发生在 某些版本的gcc。 (Johannes Schaub

它从你的第二个情况略有不同(建议实际上正在功能排除所有的头文件,以免牺牲品GCC问题),但我想我会提到它。 gcc的怪癖偶尔会咬人。

相关问题