具有函数体的纯虚拟成员函数的意义何在

What is the point of a pure-virtual member function with function body?

本文关键字:函数 虚拟成员 函数体      更新时间:2023-10-16

我刚刚惊讶地发现以下是合法的C++

struct A {
  void foo(int) const = 0;  // pure virtual
  // ...
};
void A::foo(int) const { /* ... */ }

对此,什么是合理的用例?也就是说,A::foo什么时候被调用,为什么这是正确/最好的实现?C++03和C++11之间有什么区别吗?


好吧,之前有一个问题(我没有找到)也有同样的意图。然而,那是在C++11之前。因此,我的最后一个问题仍然有效。

对此,什么是合理的用例?

如果函数有一个合理的默认实现,或者与基类相关的部分实现,但您仍然希望强制派生类覆盖它,那么这是一个很好的位置。

此外,正如注释中所指出的,您可能希望强制一个没有纯虚拟函数的类是抽象的。您可以通过使析构函数纯虚拟化来实现这一点;但是析构函数必须有一个实体,不管它是否是纯虚拟的。

A::foo什么时候会被调用?

它只能被称为非虚拟的;例如:

struct B : A {
    void f(int i) const {
        A::foo(i);    // non-virtual call
        // Do the B-specific stuff
    }
};

为什么这是正确/最好的实现?

除了一个未实现的纯虚拟函数之外,另一种选择是为部分/默认实现发明一个新名称。

C++03和C++11之间有什么区别吗?

没有。

规范用例是通过提供纯虚拟析构函数将类标记为抽象类,该析构函数必须有实现。

这是C++98之前的规则。

当然是合法的。纯虚拟函数是指它声明的类的实例不能实例化,而不是说它不能有实现
例如,它就像C#中的接口。

它提供了什么机会
1.客户端可以使用默认实现
2.具有纯虚拟析构函数的类不再引发链接器错误(当您将delete应用于指向基类的指针时:将调用派生类的析构函数,并且在调用基类的析构因子之后,如果您提交实现-链接器将引发错误)。

参考文献:在Scott Myers 的《有效C++》一书中深入描述了在纯虚拟方法中实现的需求