一个由于this指针引起的typeid()在继承时只显示基类名称的奇怪问题

发布时间 2023-06-16 10:26:04作者: imxiangzi

问题描述
先看代码

#include <iostream>
#include <string>
using namespace std;

class A{
public:
virtual string toString() {
return typeid(this).name();
}
friend ostream& operator <<(ostream& out, A& obj){
out << obj.toString();
return out;
}
};

class B : public A { };

int main(){
A a;
B b;
cout << "type name of a: " << a << endl;
cout << "type name of b: " << b << endl;
cout << "typeid(b).name(): " << typeid(b).name() << endl;
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
输出内容:

type name of a: class A *
type name of b: class A *
typeid(b).name(): class B
1
2
3
先简单介绍一下:在代码中,定义了两个类A和B,其中B是A的派生类,另外在A中重写了 << 符号,用于调用 cout,否则主函数中的 cout<<a<<endl; 会报错。

现在的问题是在输出的第2行,即 b 的类型输出为 class A *,但是如果我们在外部直接对B的对象b使用typeid取类型名称,则显示正常,非常奇怪。

问题解决
经常仔细观察发现,使用 toString()输出的名称末尾都带一个*,而在外部的没有。经过更多的测试发现确实是这样。根据C++的理解,这是指针的意思,再结合源代码,发现是对 this 指针取的名称。如果将 toString() 函数的主体内容修改为 return typeid(*this).name();,即返回this的本体,那么结果如下:

type name of a: class A
type name of b: class B
typeid(b).name(): class B
1
2
3
问题解决,结果正常了。

问题理解
根据解决方案,我们可以清楚地认识到typeid(this).name(); 返回的是当前对象的指针,指针是 A 类型的,因为其父类是A类型。如果我们在B类中,重写toString() 方法,结果返回的就是 class B *。基于以上的认识,我们可以得出这个一个结论,this 指针在基类调用时就是基类的类型,而在派生类调用时就是派生类的类型。另外,还测试了 typeid(&b).name() 返回的是 class B *,由于是在外部访问,所以结果没有任何问题。
————————————————
原文链接:https://blog.csdn.net/weixin_43145361/article/details/107366348