C++ 在虚拟功能的背景下,什么是优势? 代码示例:
考虑以下菱形层次结构:C++ 在虚拟功能的背景下,什么是优势? 代码示例:,c++,c++11,language-lawyer,virtual-functions,virtual-inheritance,C++,C++11,Language Lawyer,Virtual Functions,Virtual Inheritance,考虑以下菱形层次结构: struct A { virtual void f(){} void g(){} }; struct B : virtual A { virtual void f() override{} void g(){} }; struct C : virtual A { }; struct D: B, C { }; int main() { D d; d.f(); //B::f is cal
struct A
{
virtual void f(){}
void g(){}
};
struct B : virtual A
{
virtual void f() override{}
void g(){}
};
struct C : virtual A
{
};
struct D: B, C
{
};
int main()
{
D d;
d.f(); //B::f is called
d.g(); //B::g is called
}
我所理解的是:
就非虚拟函数g
而言,一切都很清楚:名称B::g
隐藏A::g
,即使名称A::g
可以在不通过C
隐藏的情况下访问。没有含糊不清的地方<调用代码>B::g。10.2第10页明确确认了这一点:
[注意:使用虚拟基类时,可以通过
未通过隐藏声明的子对象晶格。这不是歧义。相同的
与非虚拟基类一起使用是不明确的;在这种情况下,该名称没有唯一的实例
隐藏所有其他内容。-结束注释][示例:
此外,对于一个相关问题,他对该问题作了详尽的解释
问题是:
我不明白的是,上面提到的引用是如何与虚拟函数f
相关的。f
没有隐藏名称,是吗?只涉及重写,10.3 p.2的内容如下:
类对象S的虚拟成员函数C::vf是最终的
重写,除非S是基的最派生类(1.8)
类子对象(如果有)声明或继承另一个成员函数
在派生类中,如果
基类子对象在程序中有多个最终重写器
他身体不好
现在,在我看来,虚拟函数f
完全符合没有最终重写器的定义,并且程序的格式应该是错误的。但事实并非如此。或者是这样吗?MSVC编译得很好,但有以下警告:
警告C4250:“D”:通过支配继承“B::B::f”
老实说,我以前从来没有遇到过“支配”这个词。当我在标准中搜索它时,它在索引中只出现一次,并将我引述到我第一个引用的章节。而且,正如我已经提到的,该引用似乎只涉及名称隐藏,而不是虚拟函数重写
问题:
在D中是否有多个最终重写器f
- 在这种情况下,支配规则适用吗?它是如何遵循标准的
- 我再次引用
[10.3]/2
:
类对象S
的虚拟成员函数C::vf
是最终重写器,除非其中S
的最派生类(1.8)是基类子对象(如果有)声明或继承另一个重写vf
的成员函数。在派生类中,如果基类子对象的虚拟成员函数具有多个最终重写器,则程序格式错误
因此,在您的示例中,A::f
不是最终重写器,因为D
(最派生的类)继承了覆盖它的B::f
。B::f
是最终重写器,因此它被称为
如果有多个最终重写器(例如,如果C
也重写了f
),则程序的格式将不正确,但只有一个,因此一切正常
Clang和GCC编译这个
回答你的问题,准确地描述了你的情况,所谓支配,显然是指
[10.3]/2
中描述的行为C::f()
调用了什么?-它不算作虚拟成员函数?(从a继承)@MattMcNabb我不明白这个问题。类C
不会覆盖f
。您可以调用C::f()
,C
继承A
,而无需overriding@MattMcNabb你是说dd;dc::f();
?是的,它将根据5.2.2/1
调用A::f()
(MattMcNabb通常是通过超载解析规则发现的)@:没有函数<代码> C::f>代码>但是在代码< > >代码>范围内查找<代码> f>代码>查找<代码>::f>代码>在C++中包含一个包含<代码> fo>代码>的范围,在该范围内可以找到<代码> fo>代码>。