求教 C++中有关类的内存分配问题

wafbyy 2012-01-05 06:52:50
我们知道C++类中有关虚函数其实就是一个函数表,它指向一个地址,里面存的才是函数具体指针。问题一 类只声明但是没有实例化, 虚函数表分配么?
#include<iostream>

using namespace std;

class A
{
public:
virtual void prin(){cout<<1<<endl;};


};
class B: public A
{

public:
virtual void prin(){cout<<2<<endl;};

};


void f(A&d){d.prin();};


void main()
{
//取得类的虚函数表指针
typedef void (A::*_pfClass_fun)();
_pfClass_fun pf;
pf=&A::prin;
pf=&A::prin;

}
从代码的运行上能看pf有地址,也就说类分配了地址。那么问题是 ,当我进行实例化对象之后,类函数的指针和虚函数表所对应值不一样!这是为什么呢?
问题二 对应上面的代码 如果我将继承方式均修改为virtual 继承方式,那么A虚派生B 那么 prin()会被B 覆盖,C同理会覆盖A D会覆盖 B 和C以及A类的虚函数,问题是我在D中同时看见了A B C 在我通过虚继承方式的时候其值相等,当不用虚继承时候 不相等,这就是所谓的动态运行时确定么? 也就是当传入的对象不同的时候,我调用的不同,而没有调用的时候 是无法确定其准确的调用函数地址?求解释 谢谢
...全文
167 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
wafbyy 2012-01-07
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 forever_feng 的回复:]

第一个问题回答:
“pf=&A::prin;”是通过作用域和类型在进程的代码段直接寻址的。
如果实例化后,是通过对象的虚函数指针找到虚表,然后在虚表中寻址。

第二个问题回答:
虚拟继承为钻石形状,存在同名覆盖的问题。
[/Quote]我今天也是看书看到这个结果! 谢谢
wafbyy 2012-01-07
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 mingliang1212 的回复:]

引用 4 楼 wafbyy 的回复:
函数没有进行实例化的时候 为什么pf会有值呢 ? 不太清楚


pf 有值?你看到的是CCCCCC吗?那是debug时用的标记未初始化对象用的.

_pfClass_fun pf;
pf=&A::prin;
pf=&A::prin;

pf的确是跟prin的入口地址不同的.
因为prin是虚函数,他有多个函数板本,指针怎……
[/Quote]不是这么回事,没有初始化 有值 不是0XCCCCCC,今天看了点书明白了,是因为这个函数值是一个相对类的相对地址,要和对象结合才产生绝对地址。
iamnobody 2012-01-07
  • 打赏
  • 举报
回复
手机回复,打不了多少字,楼主参考六楼回复。
wafbyy 2012-01-06
  • 打赏
  • 举报
回复
wafbyy 2012-01-06
  • 打赏
  • 举报
回复
函数没有进行实例化的时候 为什么pf会有值呢 ? 不太清楚
wafbyy 2012-01-06
  • 打赏
  • 举报
回复
这个解释我觉得不太正确,原因是虚表本来就是一个指针你看我贴的图的第一种情况,【0】和pf的地址不一样,如果按照你说的话,[0]应该是第一地址应该为函数的真实地址了,但是实际上都不一样,显然确实解释

第二种情况代码如下:形成的是钻石型所有继承均为虚继承,这个问题产生是由于同时覆盖,取舍问题!
#include<iostream>
#include<string>

using namespace std;


class A
{
public:
virtual void prin(){cout<<1<<endl;};
void prin12(){};

};
class B:virtual public A
{

public:
virtual void prin(){cout<<2<<endl;};

};

class C: virtual public A
{
public :
virtual void prin(){cout<<3<<endl;};
};
class D: virtual public B , virtual public C, virtual public A
{
public:
virtual void prin(){cout<<4<<endl;};
void prin1(){cout<<4<<endl;};
};
void f(A&d){d.prin();};


void main()
{
A a;
//a.prin();
B b;
C c;
D d;
typedef void (A::*_pfClass_fun)();
_pfClass_fun pf;
pf=&A::prin;
pf=&A::prin;
}
nature19862001 2012-01-06
  • 打赏
  • 举报
回复
没有实例化哪儿来的动态绑定,没有动态绑定就没有虚函数表。你上面那个应该是生成了A的临时变量。传入的对象不同的时候,要看这个对象最初是哪个类的实例。因为子类和父类是可以互相强制转换的。
平凡的思想者 2012-01-06
  • 打赏
  • 举报
回复
第一个问题回答:
“pf=&A::prin;”是通过作用域和类型在进程的代码段直接寻址的。
如果实例化后,是通过对象的虚函数指针找到虚表,然后在虚表中寻址。

第二个问题回答:
虚拟继承为钻石形状,存在同名覆盖的问题。

iamnobody 2012-01-06
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 mingliang1212 的回复:]
补充一下,因为类A,B,C,D的prin的查虚函数表指令都是一样的,只是由于表不同而调用了不同的函数,所以

你可以看看
pf=&A::prin;
pf=&A::prin;

pf = &B::prin;
pf = &C::prin;

...
他们都会是一样的值.
[/Quote]

pf = &B::prin;
pf = &C::prin;


2了,,,这两句是不合法的,不过之前文字表述应该没有错.
iamnobody 2012-01-06
  • 打赏
  • 举报
回复
补充一下,因为类A,B,C,D的prin的查虚函数表指令都是一样的,只是由于表不同而调用了不同的函数,所以

你可以看看
pf=&A::prin;
pf=&A::prin;

pf = &B::prin;
pf = &C::prin;

...
他们都会是一样的值.
iamnobody 2012-01-06
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 wafbyy 的回复:]
函数没有进行实例化的时候 为什么pf会有值呢 ? 不太清楚
[/Quote]

pf 有值?你看到的是CCCCCC吗?那是debug时用的标记未初始化对象用的.

_pfClass_fun pf;
pf=&A::prin;
pf=&A::prin;

pf的确是跟prin的入口地址不同的.
因为prin是虚函数,他有多个函数板本,指针怎么知道应该指向哪个?

实际上vs2010的实现是:把pf的指针指向一个查虚函数表,然后跳转到相应的虚函数的小函数(勉强理解成函数,因为实际上是汇编的几句话)的地址.
你通过pf调用时就会先查表后跳转了.于是与一般的对象指针直接调用函数过程等效了.
youyou1912 2012-01-05
  • 打赏
  • 举报
回复
第一个问题,个人理解:
pf有地址,是因为它指向的值:是在虚表中的一个索引而已。(VS2008中,单继承虚函数指针也貌似使用了thunk)
a.prin的值,是因为你用编译器看到的值应该是:虚表+索引后的真正的值(函数地址)。

所以两个不一样。

第二问题,我用VS2008,没发现改成virtual inheritance都一样。

楼主问题在
wafbyy 2012-01-05
  • 打赏
  • 举报
回复
#include<iostream>
#include<string>

using namespace std;


class A
{
public:
virtual void prin(){cout<<1<<endl;};
void prin12(){};

};
class B: public A
{

public:
virtual void prin(){cout<<2<<endl;};

};

class C: public A
{
public :
virtual void prin(){cout<<3<<endl;};
};
class D: virtual public B , virtual public C, virtual public A
{
public:
virtual void prin(){cout<<4<<endl;};
void prin1(){cout<<4<<endl;};
};
void f(A&d){d.prin();};


void main()
{

typedef void (A::*_pfClass_fun)();
_pfClass_fun pf;
pf=&A::prin;
pf=&A::prin;


f(a);
f(b);
f(c);
f(d);


}这是代码

64,670

社区成员

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

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