28

在 C++ 中,给出纯虚函数的实现是合法的:

class C
{
public:
  virtual int f() = 0;
};

int C::f() 
{
  return 0;
}

你为什么要这样做?

相关问题:C++ faq lite包含一个示例:

class Funct {
public:
  virtual int doit(int x) = 0;
  virtual ~Funct() = 0;
};

inline Funct::~Funct() { }  // defined even though it's pure virtual; it's faster this way; trust me

我不明白为什么将析构函数声明为纯虚拟然后实现;我不明白为什么这应该更快的评论。

4

6 回答 6

23

必须始终实现已声明的析构函数,因为实现会将它们称为派生对象销毁的一部分。

如果它们提供有用的通用功能但总是需要专门化,则可以实现其他纯虚函数。在这种情况下,通常派生类实现将对基实现进行显式调用:

void Derived::f()
{
    Base::f();

    // Other Derived specific functionality
}

通常,如果您需要将类抽象化(即防止创建非派生实例),则将析构函数设为虚拟,但该类没有其他自然是纯虚拟的函数。我认为“相信我,它更快”是指这样一个事实,因为作为派生对象清理的一部分调用的析构函数不需要使用 vtable 查找机制,与典型的虚函数调用不同,可以利用内联实现.

于 2009-06-10T19:05:26.310 回答
4

如果您有派生类可以利用的通用功能。但他们也需要做其他工作。

所以派生类实现虚函数并调用底层基版本:

class X: public C
{
    public:
        virtual int f()
        {
            return C::f() + 1; // I am +1 over my parent.
        }
};
于 2009-06-10T19:12:59.930 回答
4

刚刚发现 Herb Sutter 在他的Guru of the Week #31中回答了这个问题的第一部分。

于 2009-06-10T20:15:19.150 回答
2

天,

关于为基类中声明的成员函数提供默认实现,我目前能想到的唯一原因是您希望提供行为的默认实现,作为专门研究基类的人的可能实现选择.

派生类的作者可以选择使用基类作者提供的默认实现,而不是添加自己的专门实现。

这通常是人们反对使用单独的函数来提供接口和行为的默认实现但他们仍然希望将默认实现和相关接口分开的情况。

啊,刚刚看到@Martin York 的帖子提供了一个例子。

实际上,Scott Meyers 在他的“Effective C++”一书中讨论了这一点。这是第一版的第 36 条。

高温高压

干杯,

于 2009-06-10T19:23:39.067 回答
0

因为它被认为是不正确的写法:

class Funct {
public:
  virtual int doit(int x) = 0;
  virtual ~Funct() = 0 {};
};

如果您从此类派生,仍将调用析构函数。将所有方法声明为纯虚拟方法只是为了清楚起见。你不妨这样写:

class Funct {
public:
  virtual int doit(int x) = 0;
  virtual ~Funct() {};
};

该类仍然是抽象的,因为至少有一种方法是纯虚拟的。析构函数也仍然是内联的。

于 2009-06-10T19:17:14.807 回答
0

关于虚拟析构函数的速度,这是因为析构函数是在 cpp 文件中定义的,而不是在头文件中。它与大小有关,而不是与速度有关。在《Large-Scale C++ Software Design》中有详细说明。不幸的是我不记得所有的细节,但我认为内联虚函数在 vtable 中被定义了多次。

这里有一个讨论: 内联虚函数真的是胡说八道吗?

于 2009-06-11T10:40:35.290 回答