C++ 虚指针 相关的问题

誰伴我闖荡 2011-01-15 06:56:15
今天在看Lippman的《C++对象模型》,

问题大家看了我下面写的代码应该就知道了,

在Visual Studio 2010下编写的。


class A{
public:
virtual void method1(){
}
private:
int a;
int b;
};

class B: public A{
public:
virtual void method2(){
}
private:
int c;
};

int main()
{
A* a = new A();
B* b = new B();
return 0;
}

这里,我打印了a所指向的对象的大小是12,这个很容易理解,就是
A中的a, b 的大小是8字节,然后加上vptr 4字节,所以就是12字节。。

然后打印b所指向的大小是16字节,这里有点纳闷,B中有一个变量c,
加上从A中继承的12字节,现在就是16个字节了,然而还有一个vptr,也就应该是20字节。
然而打印的却是16字节。

这里我分析应该是共享了同一个vptr,为什么?C++对象模型说的却不是这样的。

谢谢了。
...全文
244 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
誰伴我闖荡 2011-01-15
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 feng4206yu 的回复:]

在继承多个类的时候会有多个vptr..单独继承只有一个..
[/Quote]

假如一个类X继承了很多个类

然后又有一个类Y从这个X继承,同时这个Y也有个virtual函数method,

那这个virtual函数method会放在X中那个vptr所指向的虚函数列表中!
feng4206yu 2011-01-15
  • 打赏
  • 举报
回复
在继承多个类的时候会有多个vptr..单独继承只有一个..
blue822180 2011-01-15
  • 打赏
  • 举报
回复
所以我认为这种情况下还是16
誰伴我闖荡 2011-01-15
  • 打赏
  • 举报
回复
不过其实一口咬死说:一个对象只有一个vptr也不对。

只有一个vptr这种说话只是针对于一个继承链,如果一个类同时继承两个类。

也就是一个类多一个继承链,就会多一个vptr。。

-- 我的观点,也试过了,如有不对,请指出。谢谢
誰伴我闖荡 2011-01-15
  • 打赏
  • 举报
回复
我又验证了下,的确是只有一个vptr!!
blue822180 2011-01-15
  • 打赏
  • 举报
回复
这个似乎应该是虚函数的继承问题,你B是A的共有派生,当你调用B的指针的时候,我认为,他可以直接访问A不必要通过您已有的A累的指针。
誰伴我闖荡 2011-01-15
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 microsues 的回复:]

LZ:
1、派生类除了继承基类的public成员或protected成员,还继承基类的虚拟表,虚拟表里存的是类成员函数的 指针;虚拟表本身不占内存。
然而vptr不是基类的public成员或protected成员,也不是虚拟表的成员,它是指向虚拟表的一个指针;
每个含有虚拟成员函数的类都只有一个vptr;
2、你代码中的int型a和b都是private,我不明白派生类……
[/Quote]
1. 首先,虚函数列表肯定是占用内存的,不然在内存中怎么访问。
在对象中,使用一个vptr来指向这个虚函数列表的,也就是说不管基类有多少个virtual函数,
在这个对象中,vptr所占用的空间大小都是4字节(32位机器)

2.
可能是我表达的不正确,不应该用“继承”来形容private a 和b。。
因为在派生类B的对象中,在内存中有一部分是基类A的内容,也就是a和b这两个变量的值在里面了,
只是说B的对象不能访问而已。

不知道我解释的对不对,我的理解是这样的。
Microsues 2011-01-15
  • 打赏
  • 举报
回复
LZ:
1、派生类除了继承基类的public成员或protected成员,还继承基类的虚拟表,虚拟表里存的是类成员函数的 指针;虚拟表本身不占内存。
然而vptr不是基类的public成员或protected成员,也不是虚拟表的成员,它是指向虚拟表的一个指针;
每个含有虚拟成员函数的类都只有一个vptr;
2、你代码中的int型a和b都是private,我不明白派生类怎么也继承啦??请解释一下。
zy020118 2011-01-15
  • 打赏
  • 举报
回复
编译器对每个包含虚函数的类创建一个表(称为V TA B L E)。在V TA B L E中,编译器放置特定类的虚函数地址。在每个带有虚函数的类中,编译器秘密地置一指针,称为v p o i n t e r(缩写为V P T R),指向这个对象的V TA B L E。通过基类指针做虚函数调用时(也就是做多态调用时),编译器静态地插入取得这个V P T R,并在V TA B L E表中查找函数地址的代码,这样就能调用正确的函数使晚捆绑发生。为每个类设置V TA B L E、初始化V P T R、为虚函数调用插入代码,所有这些都是自动发生的,所以我们不必担心这些。利用虚函数,这个对象的合适的函数就能被调用,哪怕在编译器还不知道这个对象的特定类型的情况下。(《C++编程思想》)

每个类只有一个VPTR,指向类自己的VTABLE
arong1234 2011-01-15
  • 打赏
  • 举报
回复
不仅仅是没问题,而且是必须的,否则如果B拥有自己的vtable,当你用A的指针指向B时,调用虚函数怎么找到正确的实现?[Quote=引用 3 楼 zy020118 的回复:]
引用 1 楼 pengzhixi 的回复:
用一个vptr没问题啊,在从派生类向基类转换的时候重新设置下vptr的指向就OK了

是这样子的吗?
[/Quote]
renxu350 2011-01-15
  • 打赏
  • 举报
回复
再怎么继承,也只可能只有1个虚函数表指针
zy020118 2011-01-15
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 pengzhixi 的回复:]
用一个vptr没问题啊,在从派生类向基类转换的时候重新设置下vptr的指向就OK了
[/Quote]
是这样子的吗?
上善若水邻 2011-01-15
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 pengzhixi 的回复:]
用一个vptr没问题啊,在从派生类向基类转换的时候重新设置下vptr的指向就OK了
[/Quote]
学习了....
pengzhixi 2011-01-15
  • 打赏
  • 举报
回复
用一个vptr没问题啊,在从派生类向基类转换的时候重新设置下vptr的指向就OK了

64,654

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧