虚拟成员函数更改typeid的结果-为什么



此代码运行良好,并打印"是":

#include <iostream>
using std::cout;
using std::endl;
class A {
public:
virtual void talk() {  cout << "person talking" << endl;}
};
class B : public A {
public:
void work() { cout << "employee working" << endl; }
};
int main() {
A* pA = new B();
if (typeid(*pA) == typeid(B))
cout << "yes" << endl; // this is printed
else
cout << "no" << endl;
}

但是如果我移除虚拟关键字,它将打印";否";

#include <iostream>
using std::cout;
using std::endl;
class A {
public:
void talk() {  cout << "person talking" << endl;}
};
class B : public A {
public:
void work() { cout << "employee working" << endl; }
};
int main() {
A* pA = new B();
if (typeid(*pA) == typeid(B))
cout << "yes" << endl;
else
cout << "no" << endl; // this is printed
}

为什么会发生这种情况
为什么方法的虚拟性会影响对象的类型?

编辑:
为了让事情更加混乱,这很好:

((B*)(pA))->work(); // works fine, prints "employee working"

那么,为什么*pA只被视为A类对象(当没有虚拟关键字时(,但仍然可以调用child的work((方法呢?

typeid就是这样工作的。没有虚拟成员的类是非多态类型,并且不携带运行时类型信息。因此,在运行时无法确定它的类型。

参见[expr.typeid]/p2:

typeid应用于类型为多态类类型的glvalue表达式时,结果引用std​::​type_­info对象,该对象表示glvalue引用的最派生对象(即动态类型(的类型。

和[expr.typeid]/p3:

typeid应用于多态类类型的glvalue以外的表达式时,结果引用表示该表达式的静态类型的std​::​type_­info对象。

静态类型意味着该类型仅在编译时确定(对于A*,因此为A(。

最新更新