请参阅以下简单代码:
class A
{
public:
A() {}
virtual bool cmp(const A& a) const {cout << "cmp A" << endl; return true;}
};
class B : public A
{
public:
B() {}
~B() {}
bool cmp(const B& b) const {cout << "cmp B" << endl; return false;;}
};
int main()
{
A a1;
A a2;
B b1;
B b2;
a1.cmp(a2); // as expected
b1.cmp(b2); // as expected
a1.cmp(b1); // upcasting
// b2.cmp(a2); // conversion needed
// Here is the problematic part:
A* pa;
pa = new B;
pa -> cmp (b1); // Why why why the cmp of A runs?
return 0;
}
我无法理解它 - 有vptr和vtbl以及与调用完全匹配的函数,没有任何强制转换。那么为什么要调用A类的cmp?
非常感谢任何合乎逻辑的答案。
答案 0 :(得分:3)
因为你没有覆盖运营商。您的班级中有2个不同的运算符。
要覆盖方法或运算符,签名必须完美匹配。这意味着:
基类运算符以const A&
为参数,派生类采用const B&
。
答案 1 :(得分:1)
因为A::cmp
和B::cmp
签名不匹配。
b1
首先转换为const A &
,A::cmp
被称为
答案 2 :(得分:1)
你有两个覆盖
A::cmp(const A&)
B::cmp(const B&)
所以当你pa->cmp()
时它会调用A::cmp
,因为在编译时pa的类型是A.而且这里没有vptr的意义,因为你根本没有压倒任何东西。
如果你有
,那将是最重要的bool B::cmp(const A& b)
会覆盖签名A::cmp(const A& b)
答案 3 :(得分:0)
嗯,这是预期的,因为bool cmp(const B& b) const
不会覆盖基类的虚方法,因为它们有不同的签名。
答案 4 :(得分:0)
因为B::cmp()
签名与A::cmp()
不同。因此,B::cmp()
不会覆盖A::cmp()
,但隐藏它,它不是虚拟的,也不会通过A*
来识别。
答案 5 :(得分:0)
您在B上的方法是“隐藏”基类方法,因此您无法通过B查看。请参阅C++ FAQ以获取更详细的说明。
答案 6 :(得分:0)
请注意,虽然在覆盖虚函数中允许使用共变量返回类型,但是共变量参数类型不是!因此,您隐藏基本虚拟功能,而不是覆盖它。