标准中的哪个地方说下面调用B :: foo()是合法的?

时间:2014-05-09 18:48:54

标签: c++ inheritance c++11 implementation language-lawyer

我在派生类B::foo()中的成员函数D::foo()的定义中使用了调用DIt works,但由于我以前从未使用过这个,所以我想知道标准中引用这个结构的引用。

#include <iostream>
class B {
public:
    virtual void foo() = 0;
};

inline void B::foo() { std::cout << "B::foo()" << '\n'; } 

class D : public B {
public:
    void foo() { std::cout << "D::"; B::foo(); }
};

int main() {
  D d;
  d.foo();
}

修改

question与我的问题无关!

2 个答案:

答案 0 :(得分:3)

使用B::foo语法调用函数通常是完全合法的。

C ++标准中详述的例外情况是,当您使用纯虚函数执行通过B::foo进行调用时,您不必定义它。 10.4 / 2 :(来自@jrok)

  

[...]只有在使用或(12.4)调用qualified-id语法(5.1)时才需要定义纯虚函数。 [...]

B::foo()语法是使用qualified-id语法调用foo的示例。请注意,这与执行虚拟表查找的(this->*&B::foo)()语法不同。

纯虚函数不是&#34;将函数设置为空指针&#34;尽管有=0语法。相反,它将其标记为&#34;为了实例化此类,我要求后代覆盖此方法&#34;。碰巧,编译器倾向于将纯虚函数的虚函数表设置为指向一个错误处理程序,该错误处理程序设置一个错误(至少在调试中),你进行了一个纯虚函数调用,因为设置起来非常便宜up,它诊断在后代类实例生存期之前或之后的构造/销毁过程中对所述方法的调用。

即使您的父级定义了方法,也可以将方法标记为纯虚拟。这只表示您的子实现必须再次覆盖它。即使您定义了方法,也可以将方法标记为纯虚拟。同样,这只是告诉您的孩子实现他们必须覆盖它。

作为奖励答案,我们为什么要这样做?有时,您希望在基类中实现部分实现,以便在子实现之前或之后调用。其他时候您需要默认实现。在每种情况下,您都希望将某些代码耦合到此方法,并且您希望强制子级覆盖它。

您可以在名为virtualbefore_foo的不同非default_foo方法中实施before / after / default,或者您可以这样做。

在其他时候,在深层次结构中,从上面继承的某些方法的实现可能不再有效。所以你要=0表明孩子们必须再次覆盖它。

这两种情况都是极端情况。

我使用这种技术的最后一点是我想要消除(bar->*&Bar::foo)()烦恼。我重写Bar::foo(this->*&Bar::foo)(),允许bar->Bar::foo()做正确的事情&#34;神奇地&#34;。

答案 1 :(得分:0)

我没有仔细阅读标准,以便能够确定您所说的电话是合法的。但是,使用完全限定名称创建函数必须起作用。使用隐式限定名称只是一种快捷方式。

在您的主要功能中,当您致电:

d.foo();

等同于

d.D::foo();

第一个是隐式限定为'D :: foo'。第二个明确限定为D:foo。你也可以打电话

 d.B::foo();

这将绕过D::foo()并直接转到B::foo()