【问题标题】:Why is not overloaded function for derived class object invoked when given a pointer to base class in C++?为什么在 C++ 中给出指向基类的指针时不调用派生类对象的重载函数?
【发布时间】:2014-05-04 16:43:39
【问题描述】:

在下面的代码中

#include <iostream>
using namespace std;

class A {
  public:
    A() {}
    virtual ~A() {};
};

class B : public A {
  public:
    B() {}
    virtual ~B() {};
};

void process(const A&) {
    cout << "processing A" << endl;
}

void process(const B&) {
    cout << "processing B" << endl;
}

int main(void) {
    A* a = new B;
    process(*a);
    return 0;
}

运行它的输出变成了

processing A

但我会认为它应该是

processing B

因为a 指向派生类B 而不是A。那么为什么它调用process函数的第一个实现而不是第二个呢?

【问题讨论】:

    标签: c++ inheritance polymorphism overloading


    【解决方案1】:

    表达式*a 的静态类型是A,因为a 被声明为

    A* a = new B;
    

    编译器使用参数的静态类型解析重载函数的选择。

    即使调用虚函数,编译器也会使用对象的静态类型来调用适当的函数。不同之处仅在于编译器使用虚函数指针表来间接调用所需的函数。

    【讨论】:

    • *a的类型其实是A&amp;
    • @iavr 来自 C++ 标准:“如果表达式的类型是“指向 T 的指针”,那么结果的类型就是“T”。
    • 实例化decltype(*a)::dummy() 会产生'decltype(*a)' (aka 'A &amp;') is not a class, namespace, or scoped enumerationdecltype((*a)) 也一样。也许我错过了什么?
    • @iavr 你错过了我引用的标准的引用。
    • @iavr 编译器返回的左值与引用的原始对象相同。此引用的类型为 T。
    【解决方案2】:

    你需要使process()成为virtualAB的成员函数:

    class A {
      public:
        A() {}
        virtual ~A() {};
        virtual void process() const { cout << "processing A" << endl; }
    };
    
    class B : public A {
      public:
        B() {}
        virtual ~B() {};
        virtual void process() const override { cout << "processing B" << endl; }
    };
    
    int main(void) {
        A* a = new B;
        a->process();
        return 0;
    }
    

    在您当前的代码中,*a 的类型为 A&amp;,因此与 process(*a); 最接近的匹配是第一个重载(对于 const A&amp;)。

    【讨论】:

      【解决方案3】:

      void process(const A&amp;); 是更好的(精确)匹配,因为取消引用 A* 会得到 A&amp;

      简短的回答,但除非您想从标准中获得参考,否则没什么可说的。

      你可以dynamic_cast 得到*a 的结果,这会给你一个B&amp;,但那是很臭的设计。您可能想要的是A 中的一个虚函数,它在B 中被覆盖(假设它被称为foo)。然后,调用a-&gt;foo() 将调度到B::foo

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-03-17
        • 2017-06-17
        • 1970-01-01
        • 2019-01-08
        • 1970-01-01
        • 2014-06-16
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多