根据文件,它说[强调我的]:
当进行虚函数调用时,最终覆盖器返回的类型会隐式转换为被调用的覆盖函数的返回类型。
如何以正确的方式理解这一点?
根据下面演示代码的输出,最终覆盖器返回的类型似乎取决于实例的静态类型(将在其上调用成员函数)。
如果我错过了什么,请告诉我。
这是演示代码片段:
#include<iostream>
#include<typeinfo>
#define print() std::cout << __PRETTY_FUNCTION__ << std::endl;
class B {};
struct Base
{
virtual void vf1(){print();};
virtual void vf2(){print();};
virtual void vf3(){print();};
virtual B* vf4(){print();};
virtual B* vf5(){print();};
};
class D : private B
{
friend struct Derived; // in Derived, B is an accessible base of D
};
class A; // forward-declared class is an incomplete type
struct Derived : public Base
{
void vf1(){print();}; // virtual, overrides Base::vf1()
void vf2(int){print();}; // non-virtual, hides Base::vf2()
D* vf4(){print();}; // overrides Base::vf4() and has covariant return type
// A* vf5(){print();}; // Error: A is incomplete type
};
int main()
{
Derived d;
Base& br = d;
Derived& dr = d;
std::cout<<typeid(br.vf4()).name()<<std::endl; // calls Derived::vf4() and converts the result to B*
std::cout<<typeid(dr.vf4()).name()<<std::endl; // calls Derived::vf4() and does not convert the result to B*
B* p = br.vf4(); // calls Derived::vf4() and converts the result to B*
D* q = dr.vf4(); // calls Derived::vf4() and does not convert the result to B*
}
这是输出:
P1B
P1D
virtual D* Derived::vf4()
virtual D* Derived::vf4()
被调用的重写函数的返回类型。
注意单词选择。被调用的函数,而不是被执行的函数。您的示例专注于执行相同的功能。被调用的函数取决于你如何调用(编译时),而不是如何应答调用(运行时)。
ref
对于type的引用A&
,表达式ref.foo()
是 call to A::foo()
。调用完成后,多态性可能会启动并将执行重定向到不同的函数,但这不会改变调用的内容。你打了电话A::foo()
,但也许是B::foo()
那个人接了电话。虚函数就是这样棘手的,相互覆盖。
你介意吗?并不真地。您对结果感兴趣,而不是对谁提供结果感兴趣。只要接听电话的功能遵守由 签订的合同A::foo()
,一切都很好。如果他们愿意,他们可以换班。
在这个故事中,合约包含返回值的类型。这不能被弄乱,否则调用堆栈会被破坏。不幸的是,可能存在协变返回类型。幸运的是,B::foo()
知道如果它覆盖 for A::foo()
,它必须适应当前的合约并在返回时免费提供隐式转换。不言而喻。
尽管如此,B
仍将转换视为降级。痞子使用A
参考文献很好。让他们有自己劣等的回报价值;好东西是为那些坚持B
引用的少数歧视者保留的。这些优秀的人会打电话B::foo()
给他们,他们会跳过降级/转换。优雅。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句