铸造和多态性

时间:2012-08-24 14:02:35

标签: c++

请参阅以下简单代码:

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?

非常感谢任何合乎逻辑的答案。

7 个答案:

答案 0 :(得分:3)

因为你没有覆盖运营商。您的班级中有2个不同的运算符。

要覆盖方法或运算符,签名必须完美匹配。这意味着:

  • 名称
  • 参数
  • cv修饰符

基类运算符以const A&为参数,派生类采用const B&

答案 1 :(得分:1)

因为A::cmpB::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)

请注意,虽然在覆盖虚函数中允许使用共变量返回类型,但是共变量参数类型不是!因此,您隐藏基本虚拟功能,而不是覆盖它。