C++ 面向对象特征4 多态(Polymorphism)

简介: C++ 面向对象特征4 多态(Polymorphism)

1、对多态的理解

同一对象可以有多重层级递进身份

在不同的场合中,被外界所关注的是不同的身份,但本质和应有的行为并不会因外界眼光而改变。

比如说我自己 kali-Myon(一个实体)


生物学家会认为我(该实体)是人类 ;


教育局认为我是一名学生;


西南科技大学认为我是一名大学生。


但我目前在做什么呢?上大学对吧,我做着我自己最本质身份(大学生)的行为。


一个对象就是内存中的一个实体,它只能属于一个确定的类:最精确的子类


它可能在不同处被视为不同身份,但它本质行为方式与外界如何看待它是无关的。


为了保证一个对象执行其最本质身份的行为


我们可以利用虚函数重写和指向子类对象的父类指针来实现

2、实现多态的例子

eg1:

#include <iostream>
using namespace std;
class Human {  //定义了一个父类
public:
  virtual void say() {
      cout << "I'm human\n";
  }
};
class Student : public Human {  //子类1公有继承父类
public:
  virtual void say() {
    cout << "I'm a student\n";
  }
};
class CollegeStudent : public Student {  //子类2公有继承子类1(对于子类2来说,子类1就相当于它的父类)
public:
  void say() {
    cout << "I'm a college student\n";
  }
};
int main() {
  CollegeStudent a;  //a是子类2的一个实例化对象
  Human* p1 = (Human*)&a;  //父类指针,指向子类对象
  Student* p2 = (Student*)&a;  //父类指针,指向子类对象
  CollegeStudent* p3 = &a;
  p1->say();  //“->”是类成员访问运算符,可以被重载,它被定义用于为一个类赋予"指针"行为,常与指针引用运算符“*”结合使用
  p2->say();  
  p3->say(); 
}

由运行结果可以看出:通过指针调用的是对象本质子类的方法

(即collegestudent这个类中的say()函数)

eg2:

有很多的人(human),男的(man)应该去男厕所,女的(women)该去女厕所


但是有太多对象man1,man2,women1,man3,women2...


如何用func()函数让他们都能去到正确的厕所


我们只需定义一个上厕所的函数toilet()


男的还是女的都是人,都具有上厕所这个行为


human可能指向两种不同的实际对象

事实上func()并不关心实际是什么,反正都当成Human,能toilet就行

#include <iostream>
using namespace std;
class Human {
public:
  virtual void toilet() = 0;
};
class Man : public Human {
public:
  void toilet() {
    cout << "我去男厕所";
  }
};
class Woman : public Human {
public:
  void toilet() {
    cout << "我去女厕所";
  }
};
void func(Human * human) {
    human->toilet();
  }
int main() {
  Man man1;
  Woman woman2;
  func(&man1);
  cout << endl;
  func(&woman2);
}

运行结果:

可以看到,man1去了男厕所,woman2去了女厕所

3、多态的意义

实现代码复用


通过“虚函数+指向子类对象的父类指针”,无需针对不同的子类写相同逻辑,统一视为其共同父类,利用指针操作即可,本质是虚函数将能做什么和怎么做分离,父类指定要做什么,子类来实现具体做法。


eg3:


比如我们要设计一个函数来求图形的面积,但是我们并不知道具体是什么图形


如果没有多态,我们就需要对每种图形都实现一个函数


但是有多态,我们只需要实现一个函数

并不关心图形具体是什么,只要能求面积就行(满足父类,是个图形,就能求面积)

#include <iostream>
using namespace std;
class Shape {  //定义了一个类shape
public:
  virtual float getS() = 0;  //在父类声明了一个纯虚函数
};
class Circle : public Shape {  //圆公有继承父类shape
private:
  float radius;
public:
  Circle(float radius)
  {
    this->radius = radius;
  }
  float getS() { return 3.14 * radius * radius; }  //在子类重写虚函数
};
class Rectangle : public Shape {  //矩形公有继承父类shape
private:
  float a;
  float b;
public:
  Rectangle(float a, float b) {
    this->a = a;
    this->b = b;
}
float getS() { return a * b; }  //在子类重写虚函数
};
void display(Shape* ptr) {  //此处实现了多态:通过父类指针调用子类重写的虚函数
  cout << ptr->getS() << endl;
}
int main() {
    Circle c(1.3);
    Rectangle r(1.5, 2.3);
    display(&c);
    display(&r);
    return 0;
}

运行结果:

4、静态联编与动态联编

上述利用虚函数重写+指针实现的多态特指运行时多态,与之相对的是编译时多态


静态联编=编译时多态=函数重载=overload


动态联编=运行时多态=虚函数重写=override


联编(bind):确定具体要调用多个同名函数中的哪一个


静态联编:在编译时就确定了要调用的是哪个函数(根据多个重载函数的参数列表确)


动态联编:直到运行时才知道实际调用的是哪个函数(根据指针指向对象的实际身份)


至此,我们已经介绍完了面向对象的四个特征:封装、派生、继承、多态。

目录
相关文章
|
30天前
|
C++
9. C++虚函数与多态
9. C++虚函数与多态
27 0
|
1月前
|
安全 JavaScript 前端开发
C/C++面试题:如何理解多态?
C/C++面试题:如何理解多态?
24 0
|
1月前
|
编译器 C++
【C++】—— 多态的基本介绍
【C++】—— 多态的基本介绍
|
1月前
|
存储 资源调度 算法
Opencv(C++)系列学习---SIFT、SURF、ORB算子特征检测
Opencv(C++)系列学习---SIFT、SURF、ORB算子特征检测
|
1月前
|
算法 Java 编译器
【C++ 关键字 virtual 】C++ virtual 关键字(将成员函数声明为虚函数实现多态
【C++ 关键字 virtual 】C++ virtual 关键字(将成员函数声明为虚函数实现多态
25 0
|
5天前
|
编译器 C++
c++的学习之路:23、多态(2)
c++的学习之路:23、多态(2)
17 0
|
9天前
|
C++
面向对象的C++题目以及解法2
面向对象的C++题目以及解法2
22 1
|
20天前
|
存储 人工智能 机器人
【C++面向对象】C++图书管理系统 (源码)【独一无二】
【C++面向对象】C++图书管理系统 (源码)【独一无二】
|
25天前
|
存储 人工智能 BI
【C++面向对象】C++银行卡管理系统(源码+论文)【独一无二】
【C++面向对象】C++银行卡管理系统(源码+论文)【独一无二】
|
30天前
|
编译器 C++
C++之多态
C++之多态