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):确定具体要调用多个同名函数中的哪一个


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


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


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

目录
相关文章
|
1月前
|
编译器 C++
C++入门12——详解多态1
C++入门12——详解多态1
38 2
C++入门12——详解多态1
|
1月前
|
安全 程序员 编译器
【C++篇】继承之韵:解构编程奥义,领略面向对象的至高法则
【C++篇】继承之韵:解构编程奥义,领略面向对象的至高法则
81 11
|
1月前
|
C++
C++入门13——详解多态2
C++入门13——详解多态2
79 1
|
2月前
|
存储 安全 编译器
【C++核心】一文理解C++面向对象(超级详细!)
这篇文章详细讲解了C++面向对象的核心概念,包括类和对象、封装、继承、多态等。
26 2
|
1月前
|
存储 编译器 C语言
【C++】初识面向对象:类与对象详解
【C++】初识面向对象:类与对象详解
|
3月前
|
存储 编译器 C++
|
3月前
|
存储 安全 数据处理
【C++】C++ 超市会员卡管理系统(面向对象)(源码+数据)【独一无二】
【C++】C++ 超市会员卡管理系统(面向对象)(源码+数据)【独一无二】
|
3月前
|
存储 编译器 C++
C++多态实现的原理:深入探索与实战应用
【8月更文挑战第21天】在C++的浩瀚宇宙中,多态性(Polymorphism)无疑是一颗璀璨的星辰,它赋予了程序高度的灵活性和可扩展性。多态允许我们通过基类指针或引用来调用派生类的成员函数,而具体调用哪个函数则取决于指针或引用所指向的对象的实际类型。本文将深入探讨C++多态实现的原理,并结合工作学习中的实际案例,分享其技术干货。
75 0
|
3月前
|
算法 数据可视化 C++
【C++】C++ 学生信息管理系统(源码+面向对象)【独一无二】
【C++】C++ 学生信息管理系统(源码+面向对象)【独一无二】
|
4月前
|
机器学习/深度学习 PyTorch 算法框架/工具
C++多态崩溃问题之在PyTorch中,如何定义一个简单的线性回归模型
C++多态崩溃问题之在PyTorch中,如何定义一个简单的线性回归模型