当在C ++中给出指向基类的指针时,为什么不调用派生类对象的重载函数?

时间:2014-03-26 10:37:13

标签: c++ inheritance polymorphism overloading

在以下代码中

#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函数的第一个实现而不是第二个?

3 个答案:

答案 0 :(得分:2)

您需要process() virtual成员函数AB

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&,因此与process(*a);最匹配的是第一次重载(const A&)。

答案 1 :(得分:2)

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

A* a = new B;

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

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

答案 2 :(得分:1)

void process(const A&);是一个更好(精确)的匹配,因为解除引用A*会为您提供A&

简短的回答,但除非你想要标准的参考,否则没有更多的话要说。

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