C++基础--多态

理解多态到底是什么

  • 静态(编译时期)的多态:函数重载、模板(函数模板和类模板):

    ​ bool compare(int, int){}
    ​ bool compare(double, double){}

  • 动态(运行时期)的多态:

    在继承结构中,基类指针(引用)指向派生类对象,通过该指针(引用)调用同名覆盖方法(虚函数),基类指针指向哪个派生类对象,就会调用哪个派生类对象的同名覆盖方法,称为多态。

class Cat :public Animal 
{
public:
	Cat(string name) :Animal(name) {}
	void bark() { cout << _name << "bark:miao miao!" << endl; }

};

class Dog :public Animal
{
public:
	Dog(string name) :Animal(name) {}
	void bark() { cout << _name << "bark:wang wang!" << endl; }
 
};

class Pig :public Animal
{
public:
	Pig(string name) :Animal(name) {}
	void bark() { cout << _name << "bark:heng heng!" << endl; }
};
/*
以下这组bark API接口无法做到我们软件设计要求的"开-闭"原则
	
	"开-闭"原则 --- 对修改关闭,对扩展开放
*/
// 即便是增加动物实体类,也不用增加bark接口,这是一个通用的接口函数
void bark(Animal *p) 
{// 动态的多态
	p->bark(); // 发生动态绑定,调用各个派生类重写后的bark方法
}

int main() 
{
	Cat cat("猫");
	Dog dog("狗");
	Pig pig("猪");
	bark(&cat);
	bark(&dog);
	bark(&pig);
	return 0;
}

提供一个通用的接口函数,以基类指针接收不同派生类对象的地址,并且通过基类指针调用不同派生类对象的同名覆盖方法(虚函数)


理解抽象类

看下面例子:

定义Animal的初衷,并不是让Animal抽象某个实体的类型,而是为了:

  • string _name; 派生类通过继承抽象类,实现成员变量的复用
  • 给所有的派生类保留统一的覆盖/重写接口

实现一个抽象类:

class Animal
{
public:
	Animal(string name) :_name(name) {}
	// 纯虚函数
	virtual void bark() = 0;
protected:
	string _name;
};

拥有纯虚函数的类,叫做抽象类

抽象类不能再实例化对象,但是可以定义指针或者是引用变量(这样就可以进行动态绑定了—>多态)

再举个例子

// 把基类Car设置成抽象类,不用实例化对象
// 只负责提供复用的代码以及统一接口
class Car  
{
public:
	Car(string name, double oil) :_name(name),_oil(oil) {}
	// 获取汽车剩余油量还能跑的公里数
	double getLeftMiles() // 普通函数中调用虚函数
	{
		return _oil * getMilesPerGallon(); // 发生动态绑定
	}
	string getName()const { return _name; }
protected:
	string _name;
	double _oil;
	virtual double getMilesPerGallon() = 0; // 纯虚函数
	 
};
  • 定义派生类
class Bnze :public Car 
{
public:
	Bnze(string name, double oil) :Car(name, oil) {}
	double getMilesPerGallon() { return 20.0;}

};
class Andi :public Car
{
public:
	Andi(string name, double oil) :Car(name, oil) {}
	double getMilesPerGallon() { return 18.0; }

};
class BMW :public Car
{
public:
	BMW(string name, double oil) :Car(name, oil) {}
	double getMilesPerGallon() { return 19.0; }

};
void showCarLeftMiles(Car &car) 
{
	// 静态绑定 call Car::getLeftMiles(),但是getLeftMiles()中getMilesPerGallon()的调用是动态绑定的
	cout << car.getName() << " LeftMiles:"<< car.getLeftMiles()<<endl;
	 
}

int main() 
{
	Bnze b1("奔驰", 20.0);
	Andi a("奥迪", 20.0);
	BMW b2("宝马", 20.0);
	showCarLeftMiles(b1);
	showCarLeftMiles(a);
	showCarLeftMiles(b2);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
C语言实现多的方式有两种常见的方法: 函数指针和结构体。函数指针是一种将函数作为参数传递或返回函数的地址的方法,可以实现不同函数根据需要动调用的效果。结构体则是通过定义不同的结构体类型,并将它们作为参数进行传递,从而实现多的效果。 在C语言中,使用函数指针实现多可以通过定义一个函数指针类型,并将不同的函数赋值给该函数指针,从而在调用函数时可以根据需要动选择调用不同的函数。以一种简单的示例来说明,假设我们有一个形状的结构体,其中包含一个面积计算函数指针。我们可以定义多个不同的函数来计算不同形状的面积,然后将这些函数赋值给同一个函数指针,这样就可以在调用计算面积函数时根据传入的形状选择相应的函数进行计算。 另一种实现多的方式是使用结构体。我们可以定义一个基础的结构体类型,其中包含一个标识符字段和一个函数指针字段。然后,我们可以定义多个继承自基础结构体的派生结构体类型,每个派生结构体类型都有自己的标识符和函数指针。通过将不同的派生结构体作为参数传递给函数,并在函数内部根据传入的标识符选择相应的函数指针进行调用,就可以实现多的效果。 总结起来,C语言中实现多的方式可以通过函数指针和结构体来实现。函数指针可以根据需要动选择调用不同的函数,而结构体则可以通过定义不同的派生结构体类型,并在函数中根据传入的标识符选择相应的函数指针进行调用。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [C++教程 - How to C++系列专栏第0篇](https://blog.csdn.net/cat_bayi/article/details/132147427)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

下酒番陪绅士

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

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

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

打赏作者

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

抵扣说明:

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

余额充值