C++多态:面向对象三大特性之一

本文详细介绍了C++中的多态性,包括静态多态(函数重载和运算符重载)和动态多态(通过虚函数实现)。通过实例展示了如何在动物、猫、狗类中运用多态,以及其在工资系统和图形编程中的应用,强调了多态对于代码灵活性和可扩展性的提升。
摘要由CSDN通过智能技术生成

多态是C++面向对象三大特性之一

多态分为两类

  • 静态多态: 函数重载 和 运算符重载属于静态多态,复用函数名
  • 动态多态: 派生类和虚函数实现运行时多态

静态多态和动态多态区别:

  • 静态多态的函数地址早绑定 - 编译阶段确定函数地址
  • 动态多态的函数地址晚绑定 - 运行阶段确定函数地址

下面通过案例进行讲解多态

class Animal
{
public:
	//Speak函数就是虚函数
	//函数前面加上virtual关键字,变成虚函数,那么编译器在编译的时候就不能确定函数调用了。
	virtual void speak()
	{
		cout << "动物在说话" << endl;
	}
};

class Cat :public Animal
{
public:
	void speak()
	{
		cout << "小猫在说话" << endl;
	}
};

class Dog :public Animal
{
public:

	void speak()
	{
		cout << "小狗在说话" << endl;
	}

};
//我们希望传入什么对象,那么就调用什么对象的函数
//如果函数地址在编译阶段就能确定,那么静态联编
//如果函数地址在运行阶段才能确定,就是动态联编

void DoSpeak(Animal & animal)
{
	animal.speak();
}
//
//多态满足条件: 
//1、有继承关系
//2、子类重写父类中的虚函数
//多态使用:
//父类指针或引用指向子类对象

void test01()
{
	Cat cat;
	DoSpeak(cat);


	Dog dog;
	DoSpeak(dog);
}


int main() {

	test01();

	system("pause");

	return 0;
}

这个代码通过动物、猫、狗的类层次结构,很好地展示了C++多态的使用方式和效果。

主要逻辑:

  1. Animal类中有一个虚函数speak

  2. Cat和Dog作为子类继承Animal,并override了speak函数

  3. DoSpeak这个普通函数接收一个Animal引用作为参数

  4. 在test01中,分别创建Cat和Dog对象,传递给DoSpeak

  5. 在DoSpeak内部,调用的是Cat和Dog独有的speak实现

通过这种方式, DoSpeak函数可以适用于任何继承自Animal的对象,都会调用对应的speak实现。

满足了“定义统一接口,具体实现 deferred 到子类中”的多态特性。

这种作用机制提高了代码的灵活性和可扩展性,非常值得学习。

再举一个例子:
C++ 中多态的主要作用是实现运行时 polymorhphic 行为——允许基于具体对象类型调用对应的方法。

多态常用于:

  1. 处理相关但是行为有区别的类层次结构

  2. 实现可复用和灵活的代码

一个典型例子是工资系统:

class Employee {
public:
  virtual void pay() { 
    // 付款逻辑
  }  
};

class Manager : public Employee {
public:
  void pay() override {
    // 管理者有不同的付款逻辑
  }  
};

void payrollSystem(vector<Employee*> employees) {
  for(auto e : employees) {
    e->pay(); // 调用各自的pay方法
  }  
}

这里通过基类指针可以很方便地遍历多种类型的员工,运行时会根据实际对象类型调用他们各自的pay方法实现,无需员工类型判断,这样实现灵活多变。

除了工资系统,多态在图形编程里也有很好的应用。这里有一个使用多态绘制不同图形的例子:

class Shape {
public:
  virtual void draw() = 0;
};

class Rectangle : public Shape {
public:
  void draw() override {
    // 绘制矩形  
  }
};

class Circle : public Shape {
public: 
  void draw() override {
   // 绘制圆形  
  }
};

void drawAllShapes(list<Shape*> shapes) {
  for(auto s : shapes) {
    s->draw(); // 调用每个shape的draw绘制
  }
}

这里通过定义一个基类Shape,然后矩形类,圆形类继承实现自己的draw方法。

在绘制所有图形时,就可以统一使用Shape指针遍历,调用每种Shape子类的draw方法。

不需要判断具体类型,实现解耦可扩展。

这种基于多态实现的图形编程架构也非常常见,可以方便新增更多类型的图形,而不影响已有代码。

这就是多态性在行为扩展与复用上的优势。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

白小白的学习笔记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值