纯虚拟函数与身体的用例?

我最近才知道,在C ++中,纯虚函数可以有select地拥有一个主体。

什么是这种function的真实世界的用例?

经典是一个纯粹的虚拟析构函数:

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

你把它变成纯粹的,因为没有别的东西可以这样做,而你希望这个类是抽象的,但是你必须提供一个实现,因为派生类的析构函数会明确地调用你的类。 是的,我知道,这是一个非常愚蠢的教科书的例子,但正因为如此,这是一个经典之作。 它一定是在C ++编程语言的第一版。

无论如何,我不记得真的需要实现一个纯虚函数的能力。 对我来说,这个function似乎是唯一的原因,因为它不得不被明确地禁止,Stroustrup没有看到这个原因。

如果你觉得你需要这个function,那么你的devise很可能是错误的。

具有或不具有主体的纯虚拟函数仅仅意味着派生types必须提供它们自己的实现。

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

抽象基类(具有纯虚函数)可以为其声明的纯虚函数提供实现的一个原因是让派生类有一个简单的“默认”,他们可以select使用。 通过一个普通的虚拟函数,可以有select地重写,这并没有太多的好处 – 事实上,唯一真正的区别是你迫使派生类明确地使用“默认”的基类实现:

 class foo { public: virtual int interface(); }; int foo::interface() { printf( "default foo::interface() called\n"); return 0; }; class pure_foo { public: virtual int interface() = 0; }; int pure_foo::interface() { printf( "default pure_foo::interface() called\n"); return 42; } //------------------------------------ class foobar : public foo { // no need to override to get default behavior }; class foobar2 : public pure_foo { public: // need to be explicit about the override, even to get default behavior virtual int interface(); }; int foobar2::interface() { // foobar is lazy; it'll just use pure_foo's default return pure_foo::interface(); } 

我不确定是否有很多好处 – 也许在一个devise从抽象类开始的情况下,随着时间的推移发现很多派生的具体类实现了相同的行为,所以他们决定移动这个行为转化为纯虚函数的基类实现。

我认为把普通行为放到纯虚函数的基类实现中也是合理的,派生类可能会被修改/增强/增强。

一个用例是从构造函数或类的析构函数调用纯虚函数。

C ++标准委员会前主席,全能的Herb Sutter 给出了3种场景 ,你可能会考虑为纯虚拟方法提供实现。

亲自说一下 – 我发现他们中没有一个令人信服,一般认为这是C ++的语义瑕疵之一。 看起来C ++在构build和分离抽象父类的vtable的方法上,似乎只是在儿童build造/破坏过程中简单地暴露出来, 然后社区专家一致build议不要使用它们 。

虚拟function与身体和虚拟function与身体的唯一区别在于第二种防止实例化的存在。 你不能在c ++中标记类的抽象。

学习OOD和C ++时,这个问题可能真的让人困惑。 就我个人而言,我脑海中不断涌现的一件事就是:如果我需要一个纯虚function来实现,那么为什么要把它变成“纯”呢? 为什么不只是把它只留下“虚拟”,并已导出的好处和覆盖基地实施?

令人困惑的是,许多开发人员认为没有主体/实现是定义纯虚函数的主要目标/好处。 这不是真的! 在大多数情况下,缺less身体是具有纯虚函数的逻辑结果。 拥有纯虚函数的主要好处是定义合同! 通过定义一个纯虚函数,你想要FORCE的每一个派生来总是提供自己的函数实现。 这个“合同方面”是非常重要的,特别是如果你正在开发像公共API的东西。 由于衍生物不再被迫提供它们自己的实现,所以使函数仅仅是虚拟的不够充分,因此你可能会失去契约方面(这在公共API的情况下可能会受到限制)。 正如通常所说的:“虚拟function可以被忽略,纯虚拟function必须被忽略。” 在大多数情况下,契约是抽象概念,所以相应的纯虚函数没有任何实现是合理的。

但是有时候,因为生活很奇怪,你可能希望在衍生品之间build立一个强有力的合同,同时也希望他们从某种默认的实现中得到某种好处,同时指定合约的行为。 即使大多数书籍作者build议避免陷入这些情况,语言也需要提供安全网来防止最坏的情况发生! 一个简单的虚拟function是不够的,因为可能有逃离合同的风险。 所以C ++提供的解决scheme是允许纯虚函数也能够提供一个默认的实现。

上面引用的Sutter文章给出了具有纯虚function的有趣用例。