关于强制类型转换!

wanglf 2003-07-04 01:48:36
有这样一段代码!(摘自侯杰《深入浅出MFC第二章 Object slicing与虚拟函数》)
class CObject
{
public:
virtual void Serialize();
}
class CDocument : public CObject
{
public:
void func() {
Serialize();
}
virtual void Serialize() ;
};

class CMyDoc : public CDocument
{
public:
virtual void Serialize();
};
//------------------------------------------------------------------
void main()
{
CMyDoc mydoc;
CMyDoc* pmydoc = new CMyDoc;

cout << "#1 testing" << endl;
mydoc.func();

cout << "#2 testing" << endl;
((CDocument*)(&mydoc))->func();
//added by me
((CDocument*)(pmydoc))->func();

cout << "#3 testing" << endl;
pmydoc->func();

cout << "#4 testing" << endl;
((CDocument)mydoc).func();

}

对于test1,test3我都理解了。对于test4,书里面有解释说明,对于test2,我有一个疑惑。
1.
把CMyDoc类的指针强制转化成CDocument类的指针,那么这个指针所调用的方法,应该是CDocument的方法了,(这里也就是CDocument->func()),func()里面调用了Serialize()虚拟函数,而CDocument类也声明了这个虚拟函数,所以func()里面调用的Serialize函数就应该是CDocument的函数。
实际的结果的是调用的仍然是CMyDocument类的Serialize函数。

2.它和test4中((CDocument)mydoc).func();这种强制类型转换有什么区别呢?

哪位给解释一下?不胜感激。
困惑不一的菜鸟
...全文
75 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
wanglf 2003-07-04
  • 打赏
  • 举报
回复
多谢楼上的:
增加楼上的代码,输出结果:
调用CDocument的func();---废话
调用CDocument的Serialize()

我的解释:
原型: void MyFunc(CDocument cd),要求CDocument类对象,调用时候,一个子类被强制转换成父类的指针,再取它的值。会做出父类的一份拷贝(默认的拷贝构造函数).它的虚拟函数表中的内容和父类是一样的,所以调用的当然是父类的serialize()

扩展:
void MyFunc(CDocument* cd)
{
cd->func();
}

main里面增加:
MyFunc((CDocument*)(&mydoc));

输出结果:
调用CDocument的func();---再次废话
调用CMyDoc的Serialize();

回复吧,我就接贴。
赫赫
再次多谢
鞠躬!
liao2001 2003-07-04
  • 打赏
  • 举报
回复
我想捞点分:

1。知道虚函数是怎么实现的吗?每一个申明有虚函数的类都会包含一个虚函数表指针,它放在类的最前面,指向一个虚函数表。(什么叫虚函数表?我日!)虚函数表就是一个表,它存放类中虚函数的信息,比如参数个数、类型、函数首地址等等,每个有虚函数的类都会有自己的虚表。
当一个虚类(指包含虚函数的类)派生一个新类的时候,此时会先为新类的创建一个虚函数表,然后把它老爹的虚表内容copy过来,接下来就看看新类有没有重载虚函数,没有的话,就什么都不用做,有的话就用自己的虚函数的地址替换从他老爹那copy来的。。。
2。强制类型转化。对指针的强制类型转化仅仅是取指针所指存储单元的值的方式改变了而已,指针所指的存储单元并没有改变。把一个变量进行强制转化时,并不会改变原变量的类型,改变的仅仅是一个中间变量,而且二进制的每一位是不会改变的,改变的仅仅是访问方式,0还是0,1还是1。。

关于问题1和2,只要你看懂我上面的这些,不懂的话我也不想多说!反正没分!

再出个问题给你思考:
//此处省去你原来的代码
void MyFunc(CDocument cd)
{
cd.func();
}
然后再在你的main里加上:
MyFunc(*(CDocument*)(&mydoc));

结贴吧,没有分是不会有答案的。
wanglf 2003-07-04
  • 打赏
  • 举报
回复
**************************引用开始*********************
1、是virtual特性所起的作用,本来 CMyDoc mydoc; 但是 ((CDocument*)(&mydoc))->func();
也就是通过转换为指向基类的指针来调用基类的func()函数,看到func里是要调用ser函数的,而这个seri函数是virtual的,{也就是说,要在运行的时候才决定是调用基类的还是子类的,而这个指 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
针实际上是指向子类mydoc的,}所以ser函数就要调用子类mydoc的ser函数!
^^^^^^^^^^^^^^^^^^^^^^^
**************************引用结束*********************

我的问题:
1.“运行的时候来决定调用基类的还是子类的”,那么它强制转换的意义是什么?
也就是说:
对于普通(非virtual性质的)成员变量/成员函数,转换成基类的指针後,调用的就是基类的方法,对于virtual性质的成员函数,通过对象指针(即使是被强制转换後了的)调用成员函数时候,到底调用哪一个函数,必须视该指针的原始类型(这里指针的原始类型就是CMyDoc)而定,而不是指针实际所至的对象的类型而定。

我的理解正确吗?还往楼上的多多指教!

在此多谢!

point_to 2003-07-04
  • 打赏
  • 举报
回复
1就是一般常见的定一一个基类指针指向子类的情况
2强制类型转换没有什么特别
point_to 2003-07-04
  • 打赏
  • 举报
回复
1、是virtual特性所起的作用,本来 CMyDoc mydoc; 但是 ((CDocument*)(&mydoc))->func();
也就是通过转换为指向基类的指针来调用基类的func()函数,看到func里是要调用ser函数的,而这个seri函数是virtual的,也就是说,要在运行的时候才决定是调用基类的还是子类的,而这个指针实际上是指向子类mydoc的,所以ser函数就要调用子类mydoc的ser函数!

example:

class CObject
{
public:
virtual void Serialize(){cout<<" in object ser "<<endl; };
};
class CDocument : public CObject
{
public:
void func() {
Serialize();
}
virtual void Serialize(){cout<<" in doc ser "<<endl;};
};

class CMyDoc : public CDocument
{
public:
virtual void Serialize(){cout<<" in mydoc ser "<<endl;};
};
//------------------------------------------------------------------
void main()
{
CMyDoc mydoc;
CMyDoc* pmydoc = new CMyDoc;
/*
cout << "#1 testing" << endl;
mydoc.func();
cout << "#3 testing" << endl;
pmydoc->func();

*/
cout << "#2 testing" << endl;
((CDocument*)(&mydoc))->func();

//added by me
((CDocument*)(pmydoc))->func();



cout << "#4 testing" << endl;
((CDocument)mydoc).func();

delete pmydoc;

}
晨星 2003-07-04
  • 打赏
  • 举报
回复
1。这就是虚函数的好处呀,如果不是为了能获得这个方便,干吗还要声明成虚函数呢?
2。没有区别,这就是个非常一般的强制类型转换呀,只不过没有使用中间变量而已。

64,282

社区成员

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

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