在以下代码中
#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
函数的第一个实现而不是第二个?
答案 0 :(得分:2)
您需要process()
virtual
成员函数A
,B
:
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
。