Attention:本文旨在分析获取对象类型时程序内部是如何处理的,不能用于工程代码中,因为不同的编译器的实现是不同的,C++标准并未规定具体的实现方式。实验环境:Ubuntu 14.04 i686 GCC 4.8.4
我们可以使用typeid来获取对象的具体名称,示例代码如下:
class Base { public: virtual void doSome() { } virtual ~Base() { } }; class TypeTest: public Base { }; int main() { Base* p = new TypeTest; cout<<typeid(TypeTest).name() <<endl; cout<<typeid(p).name() <<endl; cout<<typeid(*p).name() <<endl; delete p; return 0; }
输出的结果如下:
在这段代码中前两个输出类型和第三个是不同的,因为前两个的类型编译器可以在编译期就确定了,而第三个的输出结果编译器在编译期是无法知道的,只有在执行的时候才能确定。也就是说这和C++的多态效果是一样的。
既然这也是一种多态行为,那么它的对象信息也应该能通过virtual table来获取,这样才能在运行期获取指针所指的具体类型。通过查阅资料我们可以猜测TypeTest的内存布局应该如下图所示,那么我们可以通过指针来进行验证是否如此。
验证代码:
cout<<typeid(*p).name() <<endl; printf("%s\n", (char*)(*(int*)p); // 之所以使用printf是为了防止cout进行某些重载操作 // 输出: // 8TypeTest // 8TypeTest
从输出结果来看和我们猜测的完全一致。但是在有一次我在代码的后面加了一行代码就出现问题了。
cout<<typeid(*p).name() <<endl; printf("%s\n", (char*)(*(int*)p); cout<<typeid(string).name() <<endl;
输出结果:
让我很费解的是我在下面输出别的内容居然会影响到对象的数据,当然这和typeid()处理对象是有关的,所以在实际的工程中是不能这么使用,仅限于研究对象的模型。