【C++】多态(上)

简介: 【C++】多态(上)

1. 多态的概念


多态的概念:通俗来说,就是多种形态,具体点就是去完成某个行为,当不同的对象去完成时会产生出不同的状态

举个例子,对于买票这个行为,当普通人买票时就是全价买票,学生买票就是半价,军人买票就是优先买票。这就是不同的对象执行容易个行为的时候,会有不同的状态产生。


再有一个例子,我们知道有种东西叫做大数据杀熟,这就是通过分析你的以往的行为,给使用者分为几个不同的类型,对于不同的使用者,做买东西这个行为,定价不同。这也是一种多态行为


2.多态的定义和实现


1. 虚函数

1. 虚函数的概念

使用virtual修饰的类成员函数叫做虚函数

class person
{
public:
  virtual void BuyTicket() { cout << "买票-全价" << endl; }//虚函数
};


2. 虚函数的重写

我们知道,当基类和派生类中的成员函数重名的时候,会构成隐藏(重定义),其中,如果重名函数的返回值类型参数列表完全相同,并且都是虚函数时,将会构成虚函数的重写

class person
{
public:
  virtual void BuyTicket() { cout << "买票-全价" << endl; }
};
class student : public person
{
public:
  virtual void BuyTicket() { cout << "买票-半价" << endl; }//写法一
  //void BuyTicket() { cout << "买票-半价" << endl; }//写法二
};


其中person和student中的BuyTicket函数就构成了重写

在上述student类中的BuyTicket函数还有写法二,使用写法二这种写法也是构成重写的。

✅原因:在重写基类虚函数的时候,派生类的虚函数不加virtual关键字也可以构成重写,这是因为在继承后基类的虚函数被继承下来任然保持着虚函数属性,也可以理解成:在重写的时候,只关注函数体的实现。函数返回值类型、函数名和参数列表的要求只是为了保证能够构成重写。为了规范写法,我们这里还是建议派生类的虚函数也加上virtual关键字。

2fd97f4844b66a109007a10890b2cf22.png

3. 构成虚函数重写的两个例外


1、析构函数的重写

如果基类的析构函数为虚函数,此时派生类析构函数只要定义,无论是否加virtual关键字,都与基类的析构函数构成重写,虽然基类与派生类析构函数名字不同。虽然函数名不相同,看起来违背了重写的规则,其实不然,这里可以理解为编译器对析构函数的名称做了特殊处理,编译后析构函数的名称统一处理成destructor


2、协变:基类和派生类虚函数返回值不同

派生类重写基类虚函数的时候,改变了返回值的类型。即基类虚函数返回基类类型的指针或引用,派生类返回派生类的指针或引用也构成重写

c548c79e648cc8cc0473256aa8564e79.png


2. C++11 override和final


可以看到,C++对函数重写的要求比较严格,但是在某些情况下很容易忽略,导致无法构成重写,但是这种错误在编译期间不会被报出,最终运行结果却会和预期不同,后期再debug就很麻烦,所以C++11提供了override和final两个关键字用于检测是否重写。

1. final关键字

final修饰虚函数,表示该虚函数不能再被重写

class Car
{
public:
  virtual void Drive() final {}
};
class Benz : public Car
{
public:
  virtual void Drive() { cout << "Benz" << endl; }
};


9e0d880a7731ad866226179ffff998ac.png

final的另一个作用:创建一个不能被继承的类

1d013d9f8ca59b9bb851c04fc27c1ad0.png


2.override关键字

override:检查派生类虚函数是否重写了基类的某个虚函数,如果没有重写则编译报错,如果重写了正常运行

class Car
{
public:
  virtual void Drive() {}
};
class Benz : public Car
{
public:
  virtual void Drive(int a) override { cout << "Benz" << endl; }
};


5e07b18edd73ddccccfcce25df005b49.png

相关文章
|
1月前
|
编译器 C++
C++入门12——详解多态1
C++入门12——详解多态1
38 2
C++入门12——详解多态1
|
6月前
|
C++
C++中的封装、继承与多态:深入理解与应用
C++中的封装、继承与多态:深入理解与应用
150 1
|
1月前
|
C++
C++入门13——详解多态2
C++入门13——详解多态2
79 1
|
3月前
|
存储 编译器 C++
|
4月前
|
存储 编译器 C++
【C++】深度解剖多态(下)
【C++】深度解剖多态(下)
53 1
【C++】深度解剖多态(下)
|
4月前
|
存储 编译器 C++
|
3月前
|
存储 编译器 C++
C++多态实现的原理:深入探索与实战应用
【8月更文挑战第21天】在C++的浩瀚宇宙中,多态性(Polymorphism)无疑是一颗璀璨的星辰,它赋予了程序高度的灵活性和可扩展性。多态允许我们通过基类指针或引用来调用派生类的成员函数,而具体调用哪个函数则取决于指针或引用所指向的对象的实际类型。本文将深入探讨C++多态实现的原理,并结合工作学习中的实际案例,分享其技术干货。
75 0
|
4月前
|
机器学习/深度学习 算法 C++
C++多态崩溃问题之为什么在计算梯度下降时需要除以批次大小(batch size)
C++多态崩溃问题之为什么在计算梯度下降时需要除以批次大小(batch size)
|
4月前
|
Java 编译器 C++
【C++】深度解剖多态(上)
【C++】深度解剖多态(上)
54 2
|
4月前
|
程序员 C++
【C++】揭开C++多态的神秘面纱
【C++】揭开C++多态的神秘面纱