C++多态(上)

简介: C++多态(上)

多态的概念

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

举个例子:比如说买票,普通人是全价买,学生是半价,退伍军人是优先。

多态的定义与实现

多态的构成条件与虚函数

多态很重要的前提就是先继承。

并且要去用基类的指针或者是引用去调用虚函数

被调用的函数必须是虚函数,且派生类必须对基类的虚函数进行重写

#include<iostream>
using namespace std;
class Person {
public:
  virtual void BuyTicket() { cout << "买票-全价" << endl; }//成员函数前面加一个virtual就成为虚函数
};
class Student:public Person
{
public:
  //这里是虚函数的 重写/覆盖
  virtual void BuyTicket() { cout << "买票-半价" << endl; }//条件是三同:返回值和函数名还有参数相同
};
int main()
{
  Person s1;
  Student s2;
  Person* p = &s1;
  p->BuyTicket();
  p = &s2;
  p->BuyTicket();
  return 0;
}

这里也叫做多态调用。

之前的调用都是普通调用,一直都和对象的类型有关。

多态调用是跟指向的对象有关。

如果改成普通调用就是类型是谁就去调用谁的成员函数,多态调用就是指向的对象是谁就去调用谁的虚函数。

虚函数的重写

子类虚函数可以不加virtual

#include<iostream>
using namespace std;
class Person {
public:
  virtual void BuyTicket() { cout << "买票-全价" << endl; }
};
class Student:public Person
{
public:
  //这里是虚函数的 重写/覆盖
  void BuyTicket() { cout << "买票-半价" << endl; }//只要三同,子类不加virtual也是虚函数
}
int main()
{
  Person s1;
  Student s2;
  Person* p = &s1;
  p->BuyTicket();
  p = &s2;
  p->BuyTicket();
  return 0;
}

不过这里建议都加上virtual。

协变

三同中,返回值可以不同,但是要求返回值必须是一个父子类关系的指针或者引用。

#include<iostream>
using namespace std;
class Person {
public:
  virtual Person* BuyTicket() { cout << "买票-全价" << endl; return this; }
};
class Student:public Person
{
public:
  virtual Student* BuyTicket() { cout << "买票-半价" << endl;  return this; }
};
int main()
{
  Person s1;
  Student s2;
  Person* p = &s1;
  p->BuyTicket();
  p = &s2;
  p->BuyTicket();
  return 0;
}

正常运行。

析构函数的重写

#include<iostream>
using namespace std;
class A
{
public:
  ~A()
  {
    cout << "delete s1" << endl;
    delete[] s1;
  }
protected:
  int* s1 = new int[20];
};
class B :public A
{
public:
  ~B()
  {
    cout << "delete s2" << endl;
    delete[] s2;
  }
protected:
  int* s2 = new int[20];
};
int main()
{
  A a;
  B b;
  return 0;
}

目前看来确实没什么问题,都是正常调用,来看看如下的情况:

这里导致了内存泄漏,因为析构函数不是虚函数,只能完成普通调用,所以最好在析构面前加一个virtual。

这下子就可以了。

其实子类不加virtual这里更合适,更方便。

所以在实现父类的时候,最好无脑的给析构函数加virtual。

C++11 override 和 final

final

如何实现一个不被继承的类?

C++11提供了一个关键字,类定义的时候加final:

如果放在父类的某个虚函数后面就是不让这个虚函数被重写。

但是这个情况很少见。

override

检查派生类虚函数是否重写了基类某个虚函数,如果没有重写编译报错。

重载、覆盖(重写)、隐藏(重定义)的对比

抽象类

在虚函数的后面写上 =0 ,则这个函数为纯虚函数。包含纯虚函数的类叫做抽象类(也叫接口类),抽象类不能实例化出对象。派生类继承后也不能实例化出对象,只有重写纯虚函数,派生

类才能实例化出对象。纯虚函数规范了派生类必须重写,另外纯虚函数更体现出了接口继承。

#include <iostream>
using namespace std;
class A//抽象类
{
public:
  virtual void add() = 0 {};//纯虚函数
};
class B:public A
{
public:
  void add(){}
};
int main()
{
  B s;//但是A仍然不能实例化
  return 0;
}

这就是说给某个函数必须进行重写。

抽象类一般用于,比如说车,他是一个概念,但是他有自行车,电动车,跑车等等,然后还被分为好多的品牌,所以车必须要分类出来。

接口继承和实现继承

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

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