繁体   English   中英

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

[英]Where in the Standard does it say that calling B::foo() below is legal?

我在派生类D中的成员函数D::foo()的定义中使用了调用B::foo() 它有效 ,但由于我之前从未使用过这个,我想知道支持这种结构的标准引用。

#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();
}

编辑

这个问题与我的问题毫无关系!

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

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

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

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

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

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

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

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

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

两种情况都是极端情况。

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

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

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

d.foo();

它相当于

d.D::foo();

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

 d.B::foo();

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM