在什么情况下提供纯虚函数的实现是有利的?

发布于 2024-07-24 12:11:40 字数 542 浏览 6 评论 0原文

在 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

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

In C++, it is legal to give an implementation of a pure virtual function:

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

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

Why would you ever want to do this?

Related question: The C++ faq lite contains an example:

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

I don't understand why the destructor is declared pure virtual and then implemented; and I don't understand the comment why this should be faster.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

梦在夏天 2024-07-31 12:11:40

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

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

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

    // Other Derived specific functionality
}

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

Declared destructors must always be implemented as the implementation will call them as part of derived object destruction.

Other pure virtual functions may be implemented if they provide a useful common functionality but always need to be specialized. In the case, typically derived class implementations will make an explicit call to the base implementation:

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

    // Other Derived specific functionality
}

Typically, you make a destructor virtual if you need to make a class abstract (i.e. prevent non-derived instances from being created) but the class has no other functions that are naturally pure virtual. I think the 'trust me it's faster' is refering to the fact that because destructors called as part of derived object clean up don't need to use a vtable lookup mechanism, the inline implementation can be taken advantage of, unlike typical virtual function calls.

一笑百媚生 2024-07-31 12:11:40

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

因此派生类实现了虚函数并调用底层基版本:

class X: public C
{
    public:
        virtual int f()
        {
            return C::f() + 1; // I am +1 over my parent.
        }
};

If you have so common functionality that derived class can utilize.
But they need do other work as-well.

So the derived class implements the virtual function and calls the underlying base version:

class X: public C
{
    public:
        virtual int f()
        {
            return C::f() + 1; // I am +1 over my parent.
        }
};
恍梦境° 2024-07-31 12:11:40

Just found out that Herb Sutter answered the first part of this question in his Guru of the Week #31.

第几種人 2024-07-31 12:11:40

天哪,

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

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

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

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

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

HTH

欢呼,

G'day,

Concerning providing a default implementation for a member function declared in a base class, the only reason I can think of at the moment is where you want to provide a default implementation of the behaviour as a possible implementation choice for someone who is specialising the base class.

The author of the derived class can chose to use the default implementation provided by the base class author instead of adding their own specialised implementation.

This is generally the case where people object to having separate functions to provide an interface and a default implementation of the behaviour yet they still want separation between default implementation and the associated interface.

Ah, just saw @Martin York's post which provides an example.

Actually, Scott Meyers discusses this in his book "Effective C++". It's Item 36 in the 1st edition.

HTH

cheers,

﹎☆浅夏丿初晴 2024-07-31 12:11:40

因为这样写被认为是不正确的:

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

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

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

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

Because it's regarded as ill formed to write:

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

The destructor will still be called if you derive from this class. Declaring all methods pure virtual is just for clarity. You might as well write it like this:

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

The class will still be abstract since at least one method is pure virtual. The destructor is also still inline.

跨年 2024-07-31 12:11:40

关于虚拟析构函数的速度,这是因为析构函数是在 cpp 文件中定义的,而不是在标头中定义的。 它与尺寸的关系大于与速度的关系。 在《大规模C++软件设计》中有详细解释。 不幸的是我不记得所有的细节,但我认为内联虚拟函数在虚函数表中被定义了多次。

这里有一个讨论:
内联虚函数真的毫无意义吗?

Regarding the speed of the virtual destructor this is because the destructor is defined in the cpp file and not the header. It has more to do with size than speed. It is explained in detail in "Large-Scale C++ Software Design". Unfortunately I cannot remember all the details, but I think inline virtual functions get defined multiple times in the vtable.

There is a discussion this here:
Are inline virtual functions really a non-sense?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文