我不明白为什么编译代码片段的第二个版本。AFAIK 它不应该,因为 §10.3/2
I don't understand why the second version of the snippet compiles. AFAIK it shouldn't, because of §10.3/2
由于 §10.3/2,此代码无法编译,即虚函数A::f
在D
中有多个最终覆盖器。
#include <iostream>
class A { public: virtual void f(){ std::cout << "A::f" << 'n'; } };
class B : public virtual A { public: void f(){ std::cout << "B::f" << 'n'; } };
class C : public virtual A { public: void f(){ std::cout << "C::f" << 'n'; } };
class D : public B, public C { };
int main()
{
D d;
d.f();
}
但与我的期望相反,这段代码编译。鉴于 §10.3/2 包含这句话,For convenience we say that any virtual function overrides itself
,在我看来,我们在这里遇到了上面提到的相同问题,即虚函数A::f
在D
中有多个最终覆盖器,即A::f
和C::f
。事实上,调用d.f()
调用C::f
。为什么?
#include <iostream>
class A { public: virtual void f(){ std::cout << "A::f" << 'n'; } };
class B : public virtual A {};
class C : public virtual A { public: void f(){ std::cout << "C::f" << 'n'; } };
class D : public B, public C { };
int main()
{
D d;
d.f();
}
请注意,最终覆盖器的概念适用于特定对象,而不是类:
类对象的虚拟成员函数
C::vf
S
是一个 最终覆盖器,除非派生最多的类 (1.8((其中 S 是基类子对象(如果有(声明或继承另一个成员 覆盖vf
的函数。在派生类中,如果是虚拟成员 基类子对象的函数具有多个 final。 覆盖程序格式不正确。
粗体字是我的。
标准中的示例不使用虚拟继承。D
中有两个A
子对象 - 我们称它们为 A1
和 A2
。 A::f
是A1
和B
A::f
的最终覆盖者。 C::f
是 C
中的最终覆盖器(A2
没有最终覆盖器(。D
的定义格式良好,因为没有单个基类子对象,A::f
D
中有多个最终覆盖器。
在您的示例中,对于虚拟继承,只有一个 A
对象,它是 B
和 C
的基类子对象。 A::f
不是B
的最终覆盖器,因为派生最多的类B
是基类子对象(即D
(继承了另一个覆盖A::f
的成员函数(即C::f
(。
因此,再一次,没有一个基类子对象A::f
D
中有多个最终覆盖器。 C::f
是C
和D
对象中A::f
的最终覆盖器; A
和 B
对象没有最终覆盖程序。
实际上,此代码调用C::f
:
// Setup the same as in the OP's example:
D d;
B* pB = &d;
pB->f(); // calls C::f, not A::f
相关文章:
- 条件断点在不应该触发时触发
- 你好。。。id_public变量不应该给出结果为 81 和 86 吗?为什么它为两个派生类占用不同的内存位置?
- 为什么我不应该把所有东西都放在标题中?
- 找不到 QRegularExpression 行为的任何解释。它有效,但不应该
- 在清除 istream 之前,我不应该需要取消获取它吗?
- c++ 为什么我不应该从不同的线程解锁互斥锁
- "typename"不应该只在模板函数或模板类中使用吗?
- 为不应该获得未定义行为的内容获取未定义的行为
- 两种情况下的输出不应该相同吗?
- 我得到了一个没有被忽略的无效值,因为它应该是错误的,为什么
- 默认情况下,"std::shared_ptr"不应该使用"std::d efault_delete"吗?
- void 值没有被忽略,因为它应该是(试图将 void 分配给非 void 变量?
- 错误代码 E0065 和 E0169 不应该有
- 矢量的值在不应该更改时更改
- 保证复制省略不应该适用吗?
- 不应该禁止访问私有类型吗?
- 使用匿名命名空间中的函数或另一个文件中的静态函数不应该出错吗?
- NRVO不应该保证局部命名变量和调用站点变量采用相同的地址吗?
- 类的私有成员在我的类实例化期间更改,即使他们不应该
- 我不明白为什么编译代码片段的第二个版本。AFAIK 它不应该,因为 §10.3/2