C++笔记5.00

知识点1 虚析构的引入

如何使用基类指针释放子类对象

解决方法:使用虚析构函数,通过基类指针释放子类空间

当函数调用父类的虚析构函数时,在父类中的虚函数指针指向的虚函数表中存放了子类的析构函数入口地址,从而先调用子类析构函数,子类析构函数调用完后自动调用父类的析构函数。

知识点2 纯虚函数和抽象类

  1. virtual void sleep(void) = 0;//纯虚函数格式  

如果一个类中拥有纯虚函数,那么这个类就是抽象类

抽象类不能够实例化对象

1、抽象类派生出子类,必须在子类中实现所有的纯虚函数,如果漏掉一个,那么子类也是抽象类

2、纯虚函数使用方法

案例:制作饮料

基类:煮、冲、倒、加

派生类1:煮水,冲咖啡,倒杯中,加糖和牛奶

派生类2:煮水,冲茶叶,倒杯中,加柠檬

  1. #include <iostream>  
  2.   
  3. using namespace std;  
  4.   
  5. class AbstractDrinks  
  6. {  
  7. public:  
  8.     virtual void Boil() = 0;//冲水  
  9.     virtual void Brew() = 0;//泡  
  10.     virtual void PourInCup() = 0;//倒入杯中  
  11.     virtual void PutSomething() = 0;//加料  
  12.   
  13.     void MakeDrink()//规定制作流程  
  14.     {  
  15.         Boil();  
  16.         Brew();  
  17.         PourInCup();  
  18.         PutSomething();  
  19.     }  
  20. };  
  21.   
  22. class Coffee:public AbstractDrinks  
  23. {  
  24. public:  
  25.     virtual void Boil()  
  26.     {  
  27.         cout << "煮矿泉水" << endl;  
  28.     }  
  29.   
  30.     virtual void Brew()  
  31.     {  
  32.         cout << "冲咖啡" << endl;  
  33.     }  
  34.   
  35.     virtual void PourInCup()  
  36.     {  
  37.         cout << "把咖啡倒进杯子里" << endl;  
  38.     }  
  39.   
  40.     virtual void PutSomething()  
  41.     {  
  42.         cout << "加糖和牛奶" << endl;  
  43.     }  
  44. };  
  45.   
  46. class Tea:public AbstractDrinks  
  47. {  
  48. public:  
  49.     virtual void Boil()  
  50.     {  
  51.         cout << "煮自来水" << endl;  
  52.     }  
  53.   
  54.     virtual void Brew()  
  55.     {  
  56.         cout << "泡茶叶" << endl;  
  57.     }  
  58.   
  59.     virtual void PourInCup()  
  60.     {  
  61.         cout << "把茶水倒进杯子里" << endl;  
  62.     }  
  63.   
  64.     virtual void PutSomething()  
  65.     {  
  66.         cout << "柠檬" << endl;  
  67.     }  
  68. };  
  69. //业务函数  
  70. void DoBusiness(AbstractDrinks* drink)  
  71. {  
  72.     drink->MakeDrink();  
  73.     delete drink;  
  74. }  
  75.   
  76. int main()  
  77. {  
  78.     DoBusiness(new Coffee);  
  79.     DoBusiness(new Tea);  
  80.     return 0;  
  81. }  

知识点3 纯虚析构

纯虚函数:不需要实现函数体

  1. virtual ~classname() = 0;  
  2.   
  3. classname::~classname(){};  

纯虚析构函数必须实现函数体

原因:通过父类指针释放子类对象时,先调用子类析构再调用父类析构,如果不实现父类的析构那么会无法调用。

知识点4 虚函数 纯虚函数 虚析构 纯虚析构的区分

虚函数:只有virtual修饰,有函数体(作用于成员函数)

目的:通过父类指针或引用操作子类的方法

纯虚函数:virtual修饰+=0 没有函数体,所在的类为抽象类

        目的:为子类提供固定的流程接口

虚析构:virtual修饰类中的析构函数

        目的:为了解决父类中指针指向子类对象,并且用父类指针删除子类对象的问题

纯虚析构:virtual修饰+=0 必须实现析构函数体

        目的:用父类的指针删除子类对象,同时固定接口

知识点5 重写 重载 重定义

1、重载:

同一作用域的同名函数、参数个数,参数顺序,参数类型不同

和函数的返回值没有关系

const也可以作为重载的条件

  1. int fun(int a){}  
  2. int fun(int b, int c){}  
  3. int fun(char b, int c){}  

2、重定义(隐藏)

有继承关系

子类重新定义父类的同名成员(非虚函数)

  1. class Base  
  2. {  
  3. public:  
  4.     void fun(int){}  
  5.     void fun(intint){}  
  6. };  
  7.   
  8. class Son:public Base  
  9. {  
  10. public:  
  11.     void fun(可以用不同的参数){}//重定义  
  12. };  

3、重写(覆盖)

有继承关系

子类重写父类的虚函数

函数有返回值,函数名、函数参数必须和父类中的虚函数一致

  1. class Base  
  2. {  
  3. public:  
  4.     virtual void fun(int){}  
  5. };  
  6.   
  7. class Son:public Base  
  8. {  
  9. public:  
  10.     virtual void fun(int){}//重写  
  11. };  

发表评论

邮箱地址不会被公开。 必填项已用*标注