C+++自学记录(第七章)

本文深入探讨C++中的构造函数继承、虚函数、虚类及多重继承的构造和析构过程。通过实例解释如何正确使用虚函数实现多态,解决多重继承中的二义性问题,并展示构造和析构的顺序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

第七章

1. 构造函数的继承

使用了cBase的构造方法对待ab,再自行对待c

cDerived::cDerived(int a, int b, int c) : cBase(a, b)
{
      vc=c;
}

2. 静态结合&虚函数

声明了cBase的指针变量,但是指向了cDerive的类,那么即使使用
p->disp()
调用的也是cBase的


所以引入了虚函数virtual,在基类中声明,那么在p指向cDerived的时候,调用disp()函数,用的是继承类的disp()

注意

(1)指针声明的时候必须是一个基类的!

(2)两个函数有:

相同的函数名
相同的返回值
相同的参数个数/类型

(3)

函数只在基类存在,派生类无-->基类
只在派生类有,基类无-->错误
基类和派生类都不是virtual-->基类
基类和派生类都是virtual-->派生类

(4)

声明了子类的东西,去给父类赋值,指针,引用都可以实现多态,但是直接赋值不能

void main(void){
   divide d;            //派生类对象
   base * b1=&d;  //能实现多态
   base & b2=d;    //能实现多态
   base b3=d;        //不能实现多态
}

(5)

纯虚函数=0,不会(能)生成实体==>抽象类

纯虚函数必须在子类中给出声明

子类的指针可以是父类类型,但是不能相反. 指针换一个子类指的时候,必须强制转换 p=(cDerivedA *)&dtb;

析构函数也可以成为虚函数,子类的析构顺序是: 子析构==>父析构 ,没错,虚函数的父类析构也会执行


如果用new生成一个类的变量,不使用delete,main函数结束的时候并不会执行析构函数,因为new生成的是指针,不是变量


3. 虚类

考虑如下定义:

     class cBase_A 
{
   public:
        int getx( ){…}  
    …… 
}; 

class cBase_B: public cBase_A 
{
     …… 
};

class cBase_C: public cBase_A
{   
    ……
};

class cDerived_D: public cBase_B, public cBase_C
{
     ……
}; 


cDerived_D  x;
int A=x.getx( );//就不知道该用谁的,发生编译错误
//A=x.cBase_B::cBase_A::getx( );也是错的

所以引入了虚拟基类,在基类中声明为virtual
使用方法为class cDerived_B:virtual public cBase_A

这样的话,即使发生了分歧继承,也只会有一个基类的函数


非虚拟基类下:

每个基类数据成员互不影响

x.cBase_C::setx(11); x.cBase_B::setx(10);

看x.cBase_B::getx( )是10
看x.cBase_C::getx( );是11

虚拟基类就不会这样!

4. 多重继承的构造和析构

"根据class的具体顺序"

先生成父类

再生成自己的各个定义变量对象

最终生成自己

析构按照完全相反的方向

#include <iostream.h>
class innerA
{
public:
   innerA( ){cout << "Entering innerA constructor.\n";}
   ~innerA( ){ cout << "Entering innerA destructor.\n";}
};


class innerB
{
public:
   innerB( ){cout << "Entering innerB constructor.\n";}
   ~innerB( ){ cout << "Entering innerB destructor.\n";}
};


class baseC
{
   innerA a;
public:
   baseC ( ){cout << "Entering baseC constructor.\n";}
   ~ baseC ( ){ cout << "Entering baseC destructor.\n";}
};


 class baseD
{
   innerB b;
public:
   baseD ( ){cout << "Entering baseD constructor.\n";}
   ~ baseD ( ){ cout << "Entering baseD destructor.\n";}
};


class outerA: public baseC, public baseD
       {
          innerA A1;
          innerA A2;
          innerB B1;
          innerB B2;
       public:
   outerA( ){cout << "Entering outerA constructor.\n";}
   ~outerA( ){ cout << "Entering outerA destructor.\n";}
       }
       

  void main( )
       {
          outerA x;
       }

执行之后:

       Entering innerA constructor.
       Entering baseC constructor.
       Entering innerB constructor.
       Entering baseD constructor.
       Entering innerA constructor.
       Entering innerA constructor.
       Entering innerB constructor.
       Entering innerB constructor.
       Entering outerA constructor.
Entering outerA destructor.
Entering innerB destructor.
Entering innerB destructor.
Entering innerA destructor.
Entering innerA destructor.
Entering baseD destructor.
Entering innerB destructor.
Entering baseC destructor.
       Entering innerA destructor. 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值