c++ 多态,堆,栈

来源:百度知道 编辑:UC知道 时间:2024/05/21 19:24:09
首先,有两个类,一个父类,一个子类
#include<iostream.h>
class BasicA
{
public :
virtual void get()
{
cout<<"---getBaisc---"<<endl;
}

};

class ChildA:public BasicA
{
public:
void get()
{
cout<<"---getChild---"<<endl;
}
void getn()
{
cout<<"---getCn---"<<endl;
}

};

然后我们在main中调用,我先这样做:
void main()
{
BasicA *obj = new ChildA() ;
obj->get();
((ChildA*)obj)->getn();
}
这样是可以的,
但是我这样做:
void main()
{
BasicA obj ;
obj.get();
((ChildA)obj).getn();//-----------
}

这样做却不可以,请问能不能分析透彻点,到底是怎么回事,内存方面分析

如果你在 getn() 中访问了 ChildA 的 数据 , ((ChildA*)obj)->getn();在运行时就可能会出错 ,因为 obj 指向的空间 并不包含有效的 ChildA 部分 。
对于后一种情况 ,这根本就是不能转换的 ,因为你没有相应的 转换符 ,你可以加上相应构造函数即可 ,如
class ChildA:public BasicA
{
public:
ChildA(){}
ChildA(BasicA &b){}
。。。

关于这方面的详细分析 ,请参考 THINKING IN C++ 相应部分

你这个第一种方式其实就有问题。
因为getn()只在派生类ChildA中有,在BasicA中没有,又不是虚函数。这种不是多态了,更不是动态多态了。虚函数才能动态多态。
——————————————————————
如果说第一个能运行,那是因为obj只是指针,指针类型强制转换之后,对象本身并没有变化,所以编译器宽松一点就让你转换了,但是这种很容易出错,这种程序基本可以判定为错的。如果你能运行只能理解为你的getn()并没有对ChildA实质的操作,仅仅是测试,所以没有造成错误!(一旦getn()函数是对ChildA有实际意义的函数,这个必然是要出错的)
——————————————————————
后者不行,直接强制类型转换对象!!!这样肯定不是多态了。这样实际对象的类型都变了!!!
而且根本不能这样转换,一般只能是派生类转向基类,这样虽然经常会丢些东西,但是起码可以转换。而基类转向派生类???这根本不允许!一旦派生类比基类多了数据成员,尤其是对象成员,这些成员在哪里构造?在哪里初始化?
————所以,对象之间的强制转换不是这么随便的。。。汗一个!

区别在于强帛转换的类型,第一种方式:BasicA *obj = new ChildA() ; 转换的是指针,是可以从基类强制转换到子类的。这也是C++多态的一特点。
第二种方式:BasicA obj ;
obj是类对象,是不允许从基类转换到子类的。

第2个可以这样