子类继承父类的时候会默认生成一个父类,关系如下:
也就是说子类的占用的内存大小是比父类要大的,如果父类和子类的指针相互交错指向会发生什么?
1.子类指针指向父类实体:
下面的代码简单创建了一个父类和一个子类,都拥有共同的函数print(),然后实例化一个父类指针,强转为子类指针,
调用print()函数。
#include<iostream>
class Father
{
public:
int age;
public:
Father()
{
age=50;
std::cout<<"Father create\n";
}
void print()
{
std::cout<<"Father age"<<age<<"\n";
}
~Father()
{
std::cout<<"Father delete\n";
}
};
class Child:public Father
{
public:
int age;
public:
Child()
{
age=20;
std::cout<<"Child create\n";
}
void print()//定义一个和父类的同名函数
{
std::cout<<"Child age"<<age<<"\n";
}
~Child()
{
std::cout<<"Child delete\n";
}
};
void main()
{
Father *pf=new Father;//实例化一个父类
Child *pc=static_cast<Child *>(pf);//强转为子类指针
pc->print();//访问print函数
delete pf;//释放内存
system("pause");
}
在VS2013中进行调试,可以见到父类的正常构造,父类指针正常释放,而print函数调用的是子类的print函数,并且输出了垃圾数据。为什么呢?
我们创建的实体是父类实例化的类,强转后以子类的方式在内存解释。我们知道,子类在实例化时会默认创建一个父类,所以子类的内存大小会比父类的大,所以子类的属性是没有初始化的。
如果要调用父类的函数也是可以的:
pc->Father::print();//指定访问父类print函数
2.内存释放问题:
上面的代码我们仅仅创建一个实体父类,但有两个指针,一个父类指针,一个子类指针。delete pf是没有问题的,如果delete子类指针会发生什么?
//delete pf;//释放内存
delete pc;//释放子类的指针
代码中仅仅分配了父类的大小的内存,却释放了子类一样大的内存,这会发生内存越界问题,虽然在调试中没有出现问题(因为类使用的内存比较小)。
3.父类指针指向子类实体:
void main()
{
Child *pc=new Child;
Father *pf=static_cast<Father *>(pc);
pf->print();//调用print函数
system("pause");
}
VS2013调试结果:
访问了父类的print函数,其实这也很容易理解,父类的内存大小比子类的小,所以无法访问子类的函数。
4.内存释放问题:
delete pf;//释放父类指针
如果仅仅是释放父类指针会发生内存泄漏,因为内存大小是子类实体大小。所以我们要释放的是子类指针:
//delete pf;
delete pc;//释放子类大小的内存
5.总结:
1.在子类和父类指针交错时,由于两者所占内存空间不一样,解释方式不同
2.注意内存释放问题