【C/C++】多态

本文为 C/C++ 的学习总结,讲解多态。欢迎在评论区与我交流👏

多态的基本概念

多态分为两类

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

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

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

下面通过案例讲解多态。首先我们定义动物类,并派生出猫类:

class Animal{
public:
	void speak(){
		cout << "动物在说话" << endl;
	}
};

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

再写一个执行说话的函数并进行测试,用父类 Animal 的引用指向子类 Cat 的对象,相当于 Animal & animal = cat;,C++ 中允许父子之间的类型转换,无需强制类型转换:

void doSpeak(Animal& animal) {
	animal.speak();
}

void test01() {
	Cat cat;
	doSpeak(cat);
}

如果我们运行程序,会发现运行结果为“动物在说话”,然而我们本意是想让猫说话。我们这种写法为地址早绑定,在编译阶段就确定了函数地址,调用 speak() 函数时在编译时就确定了是执行 animalspeak() 函数。如果我们想让猫说话,就要让地址晚绑定,需要在运行阶段进行绑定,只需要在函数前加关键字 virtual,变为虚函数

virtual void speak(){
    cout << "动物在说话" << endl;
}

这时的运行结果为“小猫在说话”。此时我们再从 Animal 类中派生出 Dog 子类,同样传入 Dog 的对象:

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

打印结果为:

在这里插入图片描述

这样一来,函数在运行时才能确定调用谁的 speak() 函数,如果传入 cat 就走 catspeak() 函数。

以上就实现了动态多态。总结一下,动态多态的满足条件为:

  • 继承关系
  • 子类要重写父类中的虚函数。重写是返回值、函数名、参数列表完全相同。子类加不加 virtual 都可以。

使用动态多态,我们需要让父类的指针或引用指向子类对象。即 Animal & animal = cat;

纯虚函数和抽象类

通常在父类中写的虚函数是用不上的,例如上面的 Animal 类中的 speak() 函数,我们通常会调用子类重写的函数。这时我们可以使用纯虚函数,只要类中有一个纯虚函数,我们将这个类称为抽象类

抽象类有两个特点:

  • 无法实例化对象
  • 子类必须重写抽象类中的纯虚函数,否则也属于抽象类

例如我们构建一个 Base 类,将其中的函数写为纯虚函数的形式:

class Base {
public:
    // 纯虚函数
	virtual void func() = 0;
};

我们分别在栈上和堆上实例化一个对象:

void test01() {
	Base b;
	new Base;
}

此时发生报错,抽象类是无法实例化对象的。

在这里插入图片描述

我们再派生出一个 Son 类,不重写父类的纯虚函数,并实例化一个对象:

class Son :public Base {
public:

};

void test01() {
	//Base b;
	//new Base;
	Son s;
}

此时同样会报错。我们在子类 Son 中重写父类的虚函数,并使用父类指针指向子类对象:

class Son :public Base {
public:
	virtual void func(){
		cout << "func函数调用" << endl;
	}
};

void test01() {
	//Base b;
	//new Base;
	//Son s;
	Base* base = new Son;
	base->func();
}

运行结果为“func函数调用”。

有帮助的话点个赞加关注吧 😃

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值