纯虚函数与实现

sky*_*oor 162 c++ pure-virtual

我的基本理解是没有纯虚函数的实现,但是,有人告诉我可能有纯虚函数的实现.

class A {
public:
    virtual void f() = 0;
};

void A::f() {
    cout<<"Test"<<endl;
}
Run Code Online (Sandbox Code Playgroud)

代码是否正常?

使其成为具有实现的纯虚函数的目的是什么?

Mic*_*urr 197

virtual函数必须在将直接实例化的派生类型中实现,但是基类型仍然可以定义实现.派生类可以通过使用完全范围的名称显式调用基类实现(如果访问权限允许)(通过A::f()在您的示例中调用- 如果A::f()publicprotected).就像是:

class B : public A {

    virtual void f() {
        // class B doesn't have anything special to do for f()
        //  so we'll call A's

        // note that A's declaration of f() would have to be public 
        //  or protected to avoid a compile time problem

        A::f();
    }

};
Run Code Online (Sandbox Code Playgroud)

我可以想到的用例是当有一个或多或少合理的默认行为时,但类设计者希望只显式调用默认行为.也可能是您希望派生类始终执行自己的工作但也能够调用一组通用功能的情况.

请注意,尽管语言是允许的,但这并不是我常用的东西(事实上它可以完成似乎让大多数C++程序员,甚至是经验丰富的程序员都感到惊讶).

  • 我的想法正是......除了比我说的更有说服力. (6认同)
  • 值得指出的是,使A :: f()纯意味着B*必须*实现f()(否则B将是抽象的和不可实现的).正如@MichaelBurr所指出的那样,为A :: f()提供一个实现意味着B _may_用它来定义f(). (3认同)
  • "不常用"==不良做法?我正在寻找完全相同的行为,试图实现NVI.NVI对我来说似乎是一种很好的做法. (2认同)
  • IIRC,Scot Meyer在他的一本经典着作"更有效的C++"中有一篇关于这个问题用例的优秀文章. (2认同)

Ter*_*fey 73

要清楚,你误解了什么= 0; 在虚函数意味着之后.

= 0表示派生类必须提供实现,而不是基类不能提供实现.

在实践中,当你将虚函数标记为纯(= 0)时,提供定义几乎没有意义,因为除非有人通过Base :: Function(...)明确地这样做,否则永远不会调用它.基类构造函数调用有问题的虚函数.

  • 这是不正确的.如果在纯虚拟类的构造函数中调用该纯虚函数,则将进行纯虚拟调用.在这种情况下,您最好有一个实现. (9认同)
  • 实际上,从构造函数进行基本纯调用会导致实现定义的行为.在VC++中,这相当于_purecall崩溃. (3认同)

Jar*_*Par 20

它的优点是它强制派生类型仍然覆盖方法,但也提供默认或附加实现.


Kor*_*icz 17

如果你有代码应该由派生类执行,但你不希望它直接执行 - 并且你想强制它被覆盖.

您的代码是正确的,尽管总而言之这不是经常使用的功能,并且通常仅在尝试定义纯虚拟析构函数时才会出现 - 在这种情况下,您必须提供实现.有趣的是,一旦你从该类派生,你不需要覆盖析构函数.

因此,纯虚函数的一个合理用法是将纯虚拟析构函数指定为"非最终"关键字.

以下代码非常正确:

class Base {
public:
  virtual ~Base() = 0;
};

Base::~Base() {}

class Derived : public Base {};

int main() { 
  // Base b; -- compile error
  Derived d; 
}
Run Code Online (Sandbox Code Playgroud)


rmn*_*rmn 5

你必须给一个纯虚拟析构函数的主体,例如:)

阅读:http://cplusplus.co.il/2009/08/22/pure-virtual-destructor/

(链接损坏,使用存档)


Bri*_*ndy 5

有或没有主体的纯虚函数仅仅意味着派生类型必须提供自己的实现。

如果派生类想要调用基类实现,则基类中的纯虚函数体非常有用。