[英]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_foo
或default_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.