具有实现功能的纯虚函数

问题描述 投票:163回答:8

我的基本理解是,没有针对纯虚函数的实现,但是,有人告诉我可能存在针对纯虚函数的实现。

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

void A::f() {
    cout<<"Test"<<endl;
}

上面的代码可以吗?

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

c++ pure-virtual
8个回答
198
投票

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();
    }

};

我可以想到的用例是,存在或多或少的合理默认行为,但类设计器希望仅显式调用默认行为。您可能希望派生类始终执行自己的工作,但又能够调用一组通用功能。

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


74
投票

要清楚,您误解了= 0;在虚函数之后。

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

实际上,当您将虚拟函数标记为纯函数(= 0)时,提供定义是没有意义的,因为除非有人通过Base :: Function(...)明确地进行了定义,否则将永远不会调用该定义。如果基类构造函数调用了相关的虚函数。


20
投票

它的优点是,它强制派生类型仍然重写该方法,但还提供了默认或附加实现。


17
投票

如果您有应由派生类执行的代码,但是您不希望直接执行该代码,则希望强制其被覆盖。

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

因此,纯虚拟函数的一种合理用法是将纯虚拟析构函数指定为“非最终”关键字。

以下代码出奇的正确:

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

Base::~Base() {}

class Derived : public Base {};

int main() { 
  // Base b; -- compile error
  Derived d; 
}

5
投票

例如,您必须将主体赋予纯虚拟析构函数:)

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

(Link broken, use archive)


4
投票

是的,这是正确的。在您的示例中,派生自A的类同时继承接口f()和默认实现。但是,您必须强制派生类实现f()方法(即使只是调用A提供的默认实现)。

Scott Meyers在Effective C ++(第二版)]中讨论了这一点>#36区分接口的继承和实现的继承。项目编号在最新版本中可能已更改。


4
投票

具有或不具有主体的纯虚函数仅表示派生类型必须提供其自己的实现。


2
投票

'虚拟void foo()= 0;'语法并不意味着您不能在当前类中实现foo()。 这也不意味着您必须在派生类中实现它

© www.soinside.com 2019 - 2024. All rights reserved.