类指针的强制转化问题?
今天看到有这样的写法(CMainFrame*)m_pMainWnd,这样写的目的是不是为了调用派生类成员函数啊?
自己写了一个程序试了一下,是可以的。
可是有一点不明白:基类在创建对象之后,分配的内存不就固定下来了么?为什么指向该内存空间的“派生类指针”能够调用其派生函数呢?难道这内存内存自动增长了?
高手帮忙解答一下啊,谢谢!~
下面是自己写的试验程序:
#include <iostream>
using namespace std;
class BaseClass
{
public:
BaseClass();
OutPutBase();
protected:
private:
int a;
};
class GenClass:public BaseClass
{
public:
GenClass();
OutPutGen();
protected:
private:
int b;
};
BaseClass *bCls=new BaseClass;
GenClass *pg1=(GenClass*)bCls;
void main()
{
pg1->OutPutGen();
}
BaseClass::BaseClass()
{
cout<<"Base Class! "<<endl;
}
GenClass::GenClass()
{
b=1;
cout<<"Gen Class! "<<endl;
}
BaseClass::OutPutBase()
{
a=0;
cout<<a<<endl;
}
GenClass::OutPutGen()
{
b=1;
cout<<b<<endl;
}
问题点数:20、回复次数:13Top
1 楼qhfu(改个名字)回复于 2005-10-17 17:16:48 得分 0
调用虚函数时, 主要是跟编译期的邦定有关系,(CMainFrame*)m_pMainWnd 这样就会从 CMainFrame类的vptr表中查找,如果 CMainFrame类中没有 那个函数就会编译出错,, 而运行时,是跟实际指向的类型邦定,也就是派生类邦定。。上面说的是虚函数调用,,
如果不是虚函数的话,那么调用时就是编译期绑定。
指针类型的内存大小都是一样的, 4个字节Top
2 楼bm1408(向va_list学习~不用VC好多年~)回复于 2005-10-17 17:18:44 得分 2
vtable的伤用了~~Top
3 楼tidyduck(辨不清东南西北)回复于 2005-10-17 17:34:21 得分 0
回复人: qhfu(崩溃) ( ) 信誉:105
=================================
您的意思是在编译的时候就指定分配派生类那么多的内存吗?
Top
4 楼fly_qj(青蛙王子)回复于 2005-10-17 18:39:05 得分 3
那C++的多态体现在哪去了?
你的问题正是多态的具体体现呗。Top
5 楼tidyduck(辨不清东南西北)回复于 2005-10-17 20:52:56 得分 0
刚刚又看了一下,发现用派生类指针指向基类的对象时,指向的对象长度发成了增长。
我想知道内存空间是如何变化的呢?如果该对象在内存中增长,那这个对象后面的内存为什么不会被覆盖呢?Top
6 楼qhfu(改个名字)回复于 2005-10-17 23:34:43 得分 0
内存是运行期分配的,如:
Base * b = new Derived;
b通过new得到的内存大小是由 new后面这个派生类型决定的,,而不是由b的指针类型决定的。Top
7 楼tidyduck(辨不清东南西北)回复于 2005-10-17 23:42:58 得分 0
可是在用派生类指针之前和之后的对象长度不一样啊?
#include <iostream>
using namespace std;
class BaseClass
{
public:
BaseClass();
OutPutBase();
protected:
private:
int a,aa;
};
class GenClass:public BaseClass
{
public:
GenClass();
OutPutGen();
protected:
private:
int b;
};
BaseClass bCls;//基类对象
GenClass *pg1=(GenClass*)&bCls;//指向该对象的是一派生类指针
void main()
{
cout<<sizeof(bCls)<<endl;
cout<<sizeof(*pg1)<<endl; //两个结果并不一样
}
BaseClass::BaseClass()
{
cout<<"Base Class! "<<endl;
}
GenClass::GenClass()
{
b=1;
cout<<"Gen Class! "<<endl;
}
BaseClass::OutPutBase()
{
a=0;
cout<<a<<endl;
cout<<sizeof(this)<<endl;
}
GenClass::OutPutGen()
{
b=1;
cout<<b<<endl;
cout<<sizeof(this)<<endl;
}
Top
8 楼qhfu(改个名字)回复于 2005-10-18 00:02:54 得分 0
BaseClass bCls;//基类对象
GenClass *pg1=(GenClass*)&bCls;//指向该对象的是一派生类指针
(1)让派生类的指针指向基类的对象是一种错误的做法。
(2)这里并不存在多态, 只是把一个类型的指针强制转化成另外一个类型的指针解释。
(3)OutPutBase(); 这个函数没有返回类型竟然也行。
(4)cout<<sizeof(*pg1)<<endl; pg1的类型是GenClass编译期决定的,所以sizeof(*pg1)只是sizeof(Genclass);Top
9 楼tidyduck(辨不清东南西北)回复于 2005-10-18 09:46:09 得分 0
回复人: qhfu(崩溃) ( ) 信誉:105 2005-10-18 00:02:00 得分: 0
BaseClass bCls;//基类对象
GenClass *pg1=(GenClass*)&bCls;//指向该对象的是一派生类指针
(1)这只是个测试程序,原程序的用法是
HMENU hMenu = ((CMainFrame*) m_pMainWnd)->NewMenu();
这个程序是一个图标菜单的例子,我觉得他是为了调用派生类的函数才这样做的,我的测试程序也通过了啊。
(2)同意,我也觉得不存在多态问题。
(3)为什么一定要有返回值呢?
(4)刚刚看了你的解释:
Base * b = new Derived;
b通过new得到的内存大小是由 new后面这个派生类型决定的,,而不是由b的指针类型决定的。
可是由派生类指针指向基类对象所在的内存区域之后,再sizeof该指针对象发现其长度增加,这看上去是理所当然的,派生类嘛,自然要比基类的长度大了。问题是增加的这部分内存为什么不会覆盖原基类所占用内存的后面的部分呢?Top
10 楼qhfu(改个名字)回复于 2005-10-18 11:53:19 得分 5
(1)这只是个测试程序,原程序的用法是
HMENU hMenu = ((CMainFrame*) m_pMainWnd)->NewMenu();
这是一个派生类指针转化为基类指针。
(3)为什么一定要有返回值呢?
除了构造函数和构析函数, 还有什么函数能没有返回值,至少也要返回一个void 有的编译器好像默认返回void 所以能通过,但是这决定不是正确的编程方法,
(4)内存是不会在运行期无故增加,除了用new,,用强制解释只能暴力的把内存解释成不同的东西.
(5)越描越黑了, 建议你先把c++基础知识学扎实点 呵呵Top
11 楼tidyduck(辨不清东南西北)回复于 2005-10-18 14:54:29 得分 0
(1)HMENU hMenu = ((CMainFrame*) m_pMainWnd)->NewMenu();
有关于m_pMainWnd的定义如下:
CWnd* m_pMainWnd; // main window (usually same AfxGetApp()->m_pMainWnd)
而有关CMainFrame的定义如下:
class CMainFrame : public CFrameWnd
{...}
难道m_pMainWnd是“派生类”指针,被转化成CMainFrame这个“基类”基类了?
我虽然C++学得一般,但谁是基类谁是派生还是能分清楚的!
(2)有关于是否有多态的问题,我问过几个网友,目前说法还不统一。
(3)无返回值的函数是C的用法,而C++对C是兼容的,在一些小程序上,我觉得完全可以使用。
(4)您是否运行过了我的程序呢?请问指针对象的长度增加如何解释?Top
12 楼yanjun_1982(山泉农夫)回复于 2005-10-18 15:35:11 得分 10
sizeof是编译时候使用的,它关心的不是指针指向的对象是什么类型,而是指针本身是什么类型.
至于你能使用基类指针来访问派生类的的函数,如果这个函数不涉及派生类的成员变量的话,
是没什么问题.因为对象内存中不存放成员函数的地址.
如果涉及到了派生类的成员变量,程序就不会按你想象中运行,
因为基类里并没有派生类的成员变量,基类对象内存空间没有被扩大.
PS:有virtual就有多态.
PS:我没运行过你的程序,也没留意看.Top
13 楼yanjun_1982(山泉农夫)回复于 2005-10-18 15:50:34 得分 0
嗯,其实你的想法也是有少少正确的.
基类指针能够访问到派生类的成员,这个派生类的成员的地址是放在基类对象内存空间之外的,
对这个成员变量进行访问是非法的,
在运行时会出错:对象周边空间被腐蚀(Stack around the variable "base_obj" was corrupt)Top




