2012-01-19 63 views
70

这可能看起来像一个简单的问题,但我无法在其他地方找到答案。是否需要在派生类中实现所有虚函数?

假设我有以下几点:

class Abstract { 
public: 
    virtual void foo() = 0; 
    virtual void bar(); 
} 

class Derived : Abstract { 
public: 
    virtual void foo(); 
} 

它是确定该类派生没有实现吧()函数? 如果不是我的所有派生类都需要bar()函数,但有一些做。 是否需要在派生类中实现抽象基类的所有虚函数,还是只需要在纯虚函数中实现? 感谢

回答

59

派生类做必须实现所有虚拟函数本身。他们只需要执行纯粹的。 这意味着问题中的Derived类是正确的。它继承bar实施从它的祖先类,Abstract。 (这里假定Abstract::bar某处实现的,这个问题的代码声明的方法,但不定义它,你可以在线将它定义为Trenki's answer节目,也可以单独定义它。)


即使如此,只有派生类将是实例化。如果派生类没有直接实例化,但只存在于更多派生类的基类中,那么这些类将负责实现其所有纯虚方法。允许层次结构中的“中间”类留下一些纯粹的虚拟方法,就像基类一样。如果“中间”类确实使用实现纯虚方法,那么它的后代将继承该实现,因此它们不必自行重新实现它。

+2

即使这个(实施纯虚函数)仅当它们旨在被实例化(相对于作为一个抽象基类本身)。 –

+0

这就是我的想法。但是我在我的项目中这样做,我得到一个链接错误,说Derived :: bar()有一个“无法解析的外部符号”;但是我从来没有在Derived中声明bar,那么为什么链接器在寻找函数体? – mikestaub

+0

@pixelpusher当然'Derived :: bar'有一个函数体,即'Abstract :: bar'。所以看起来翻译单元在哪里被定义(它甚至定义在任何地方?)没有链接到它被调用的翻译单元中。 –

3

是的,这很好......你只需要实现任何纯虚函数就可以实例化一个派生自抽象基类的类。

31

只有纯粹的虚拟方法必须在派生类中实现,但是您仍然需要其他虚拟方法的定义(而不仅仅是声明)。如果你不提供一个,链接器可能会抱怨。

所以,只是把你的{}虚拟可选方法后,为您提供了一个空的默认实现:

class Abstract { 
public: 
    virtual void foo() = 0; // pure virtual must be overridden 
    virtual void bar() {} // virtual with empty default implementation 
}; 

class Derived : Abstract { 
public: 
    virtual void foo(); 
}; 

一个更复杂的默认实现将进入一个单独的源文件虽然。

+2

宾果。这是我的问题,非常感谢。 :) – mikestaub

+0

语法错字? – Goldname

7

ISO C++标准规定必须定义非纯虚拟类的所有虚拟方法。

简单的说,规则是:
如果你的派生类overiddes的基类的虚方法,那么它应该提供一个定义为好,如果没有,那么基类应该提供方法的定义。

根据代码示例中的上述规则,virtual void bar();需要Base类中的定义。

参考:

C++ 03标准:10.3虚函数[class.virtual]

在类声明的虚函数将被定义,声明或纯(10.4)在该班级,或两者;但不需要诊断(3.2)。

因此,无论您应该使该功能纯虚拟还是为其提供定义。

gcc faq doccuments它,以及:

的ISO C++标准指定不在纯虚拟必须被定义,但类的所有虚拟方法不需要任何诊断为侵犯这条规则[class.virtual]/8。基于这个假设,GCC将只发射隐含定义构造函数,赋值运算符,析构函数,并在翻译单元,其限定了第一等非内联方法的类的虚拟表。

因此,如果您不能确定这种特殊的方法,接头可以抱怨缺少的定义,显然不相关的符号。不幸的是,为了改善这个错误信息,可能有必要改变链接器,而这并不总是可以完成的。

解决方案是确保不在纯所有虚拟方法被定义。请注意,即使它被声明纯虚拟[class.dtor]/7析构函数必须定义。

0

是的,它的正确派生类必须覆盖父类中的纯虚拟函数。具有纯虚函数的父类仅被称为抽象类,因为它的子类必须给它们自己的纯虚函数体。

对于一般虚拟函数: - 它没有必要进一步重写它​​们,因为某些子类可能有一些功能,有些可能没有。虚拟功能的机制

主要目的是运行时多态性,纯虚函数(抽象类)的主要目的是使其强制具有相同的名称与功能自己的身体。

相关问题