C++基础(三)

 

一、C++的三大特性

  封装、继承、多态

  多态简而言之就是用父类型的指针指向子类型的实例,然后通过父类的指针调用实际子类的成员函数。这种技术可以让父类的指针具有“多种形态”。

  多态意味着多种形态,当类之间存在层次结构,且不同类之间通过继承关联时,就会用到多态。  

  需要在基类中将公有函数名设置为虚函数,此时编译器就会通过指针内容调用函数,而非通过指针类型调用函数(静态多态)。

  1、多态

  普通函数的继承是实现继承,派生类继承了基类函数,继承的是函数的实现,虚函数的继承是一种接口继承,派生类继承的是基类虚函数的接口,目的是为了重写,达成多态。所以,如果不是为了实现多态,不要把函数定义成虚函数

  2、虚表与vptr指针

  当类中声明虚函数的时候,编译器会在类中生成一个函数虚表。虚函数表是一个存储类成员函数指针的数据结构,这个虚函数表由编译器自动生成和维护,virtual成员函数会被编译器放入虚函数表中,存在虚函数时,每个对象中都有一个指向虚函数表的指针。

二、const的作用

  1、定义const常量,可以防止意外的修改

  2、相较于#define便于进行类型安全检查

  3、相较于#define更节约内存空间

  4、编译器不为普通const菜场里那个分配存储空间,使得没有存储和读内存的操作,提高了效率。

三、析构函数

  是类的一种特殊的成员函数,会在每次删除所创建的对象时执行,它不会返回任何值,也不会有任何参数。

  析构函数有助于在跳出程序前释放资源。 

  基类的析构函数最好写成虚基类,此时派生类的析构函数会自动重写基类的析构函数,可以理解为编译器对析构函数做了特殊处理。

四、内联函数(inline)

  目的是提高函数的执行效率,但是必需要和函数定义体放在一起,仅与函数声明体放在一起没有任何意义。

  缺点:滥用内联函数会让程序变慢。

五、钻石继承问题(菱形继承)

  

 

  问题描述:D类中会有两份A类的成员(包括数据和方法),所以D的对象会包含A的两个子对象,这会导致调用函数不明确(D的对象不清楚应该调用B中的函数还是C中的函数)。

 

  解决方法:class B : virtual public A{};

       class C : virtual public A{};

  即为B、C虚继承A类后,类D中将会只有一个A的子对象。 

 六、同名覆盖问题

  场景描述:父类指针指向子类时,调用了一个在父类和子类中均存在的函数(在子类中把父类的此函数进行了重写),此时调用的是哪个函数。

  1、父子间的赋值兼容

  (1)子对象可以直接赋值/初始化父类对象。

  (2)父类指针可以直接指向子类对象。 

  (3)父类引用可以直接引用子类对象。

  2、父类指针(引用):当使用父类指针直接指向(引用)子对象时

  (1)子类退化为父类对象。

  (2)只能访问父类中定义的成员

  (3)可以直接访问被子类覆盖的同名成员

  3、特殊的同名函数

  子类中可以重定义父类中已经存在的同名函数,这种重定义发生在继承中,称为函数重写。

  若采用父类指针指向子类对象,并调用在子类中重写过的函数,此时会调用父类对象中的函数为了解决此问题,引入多态的概念(通过虚继承避免)。

七、引用

  引用就是某一变量(目标)的一个别名,对引用的操作和对变量直接操作完全一样。

  引用的声明方法: 类型标识符 &引用名=目标变量名。

  int a;

  int &ra =a; 此时定义了一个引用ra,它是变量a的引用,也即别名。

  引用只是一个别名,本身不是数据类型,也不占用存储单元,系统也不分配存储单元,对引用取地址等价于对目标变量取地址。

  无法建立对数组的引用。

    1、常引用

    const 类型标识符 &引用名= 目标变量名

    避免通过引用更改目标变量的值,达到了引用的安全性。

    2、引用作为返回值

    (1)、 以引用返回函数值的时候,定义函数时需要在函数名前加&。

    (2)、用引用返回一个函数值的好处是,在内存中不产生被返回值的副本,可以节约内存开销。

  

  

 

posted @ 2022-03-05 14:04  czy1223  阅读(40)  评论(0)    收藏  举报