2.父类指针与子类指针交错

子类继承父类的时候会默认生成一个父类,关系如下:

也就是说子类的占用的内存大小是比父类要大的,如果父类和子类的指针相互交错指向会发生什么?

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.注意内存释放问题

猜你喜欢

转载自blog.csdn.net/weixin_40850689/article/details/84189712