由class="tags" href="/tags/VECTOR.html" title=vector>vector造成的对象切片
在编写一个小实例的时候,发现用class="tags" href="/tags/VECTOR.html" title=vector>vector存放基类,而试图调用子类的虚函数是行不通的!代码如下:
这样的结果是我当初的构想完全不一样的,那么为什么会造成这种现象呢?
先从对象大小的角度来看:
由于声明的是class="tags" href="/tags/VECTOR.html" title=vector>vector<base>,那么每个元素的大小就是sizeof(base),如果转入的是子类,那实际上进入class="tags" href="/tags/VECTOR.html" title=vector>vector的“合法”大小也仅为sizeof(base),超过这部分的大小,将被忽略,这就是对象切片(Object Slicing)。
再从虚函数表的角度来看:
我们知道,C++实现多态的原理就是利用了虚函数表,每个对象在定义后的头4个字节就是一个指向虚函数表的指针(而虚函数表则是每个类共享一份),这是在编译器就确定的,在运行时再通过虚函数表的指针找到真正的实现函数的首地址。那么心细的朋友可能发现了,代码:
v1.push_back( child() );
明明定义了一个child对象,也就是在临时对象中的虚函数表指针是指向child的show函数的,那么放入v1的对象也应该是拥有指向child的虚函数表指针的吧?
答案是否定的,我们来看push_back的代码(GCC):
就是说,其实在class="tags" href="/tags/VECTOR.html" title=vector>vector中存放的已经是彻底的base了。。。
因此通过声明class="tags" href="/tags/VECTOR.html" title=vector>vector<base>来实现多态是不行的。
那么如果才能通过class="tags" href="/tags/VECTOR.html" title=vector>vector来实现多态呢?
可以用存放指针的方法:class="tags" href="/tags/VECTOR.html" title=vector>vector<base*> 示例代码如下:
当然在实际项目中用智能指针会是更好的选择!