C++父类子类指针与多态的一些问题

上篇文章简要讲了多态场景下的一个坑,今天对父类指针和子类指针分别指向一个子类对象的访问权限以及调用析构函数问题。

class A
{
 public:
     virtual void func(int val = 1){ std::cout<<"A->"<< val <<std::endl;}
     virtual void test(){ func();}
 };
 
 class B : public A
 {
 public:
     void func(int val = 0){ std::cout<<"B->"<< val <<std::endl; }
 };
 
 int main(int argc ,char* argv[])
 {
    B*p1 = new B;
    A*p2 = new B;
    p1->test();
    p2->test();
     return 0;
 }

这里不管是p1还是p2调用test()函数,最终结果都是B->1,但是运行机制不一样。先分析p1->test(),p1->test() 是通过派生类指针调用,直接访问 A::test(),又因为B重写了func()函数,会调用 B::func()(动态绑定),不过默认参数的值还是由 A::func() 决定(静态绑定),主要原因还是因为A的func()是虚函数; p2->test()的分析差别在于p2是父类指针,加上虚函数满足了多态的条件,而p1是派生类指针,不满足多态。

是否可以理解成 p1 和 p2 都指向一个 B 类对象,可以访问 B 类的全部内容?
p1 和 p2 都指向一个 B 类对象,这是正确的,所以在有虚函数func()时才能都调用B的func()。
但是p1(B* 类型):可以访问 B 类的全部内容(包括从 A 继承的部分和 B 自己定义的部分);而p2(A* 类型):只能访问 A 类的成员和 B 类重写的虚函数,不能直接访问 B 类的特有成员。

对代码进行修改,说明虚函数对析构的影响。

class A
{
 public:
     virtual void func(int val = 1){ std::cout<<"A->"<< val <<std::endl;}
     virtual void test(){ func();}
     ~A()
     {
     	cout<<"~A()"<<endl;
     }
 };
 
 class B : public A
 {
 public:
     void func(int val = 0){ std::cout<<"B->"<< val <<std::endl; }
      ~B()
     {
     	delete arr;
     	cout<<"~B()"<<endl;
     }
 private:
 	int* arr=new int[10];   
 };
 
 int main(int argc ,char* argv[])
 {
    B*p1 = new B;
    A*p2 = new B;
   // p1->test();
   // p2->test();
    delete p1;
    delete p2;
     return 0;
 }

对于delete p1,显然是先调用派生类析构函数再调用基类析构函数;但是对于delete p2,由于p2是A*,只能访问到派生类B的基类部分,所以只会调用~A(),没有调用B的析构函数,且~B() 存在资源释放,此时就会造成内存泄漏。当给~A() 前加上virtual时,无论派生类B的析构函数是否加关键字,都与基类的析构函数构成重写,虽然基类和派生类析构函数名不同看起来不符合重写的规则,实际上是编译器对析构函数名称做了特殊处理,编译后析构函数的名称统一为destructor,此时就不存在资源泄漏问题。
////简单总结就是
如果基类的析构函数不是虚函数,通过基类指针删除派生类对象时,会导致派生类的资源泄漏。将基类的析构函数声明为虚函数可以解决这个问题。
析构函数的重写:只要基类的析构函数是虚函数,派生类的析构函数就会自动成为虚函数(即使没有显式声明 virtual),不仅是析构函数,其他只要是基类函数有virtual,那么派生类的virtual可加可不加。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值