C++多态的理解

1.多态的概念及分类

多态是面向对象程序设计的一个重要特征。多态的字面意思就是多种状态,在面向对象的程序设计中,一个接口,多种实现即为多态。c++的多态性具体体现在编译和运行两个阶段。编译时多态是静态多态,在编译时就可以确定使用的接口。运行时多态是动态多态,具体引用的接口在运行时才能确定。

静态多态和动态多态区别其实只是在什么时候将函数实现和函数调用关联起来,是在编译时期还是运行时期,即函数地址是早绑定还是晚绑定。静态多态是指在编译期间就可以确定函数的调用地址,并产生代码,这是静态的,也就是说地址是早绑定。静态多态也被叫做静态联编。动态多态是指函数在运行期间才能确定函数的调用地址,这是动态的,也就是说地址是晚绑定。

1.1 静态多态

主要通过函数重载、泛型编程来实现。比如说,相同的函数名,可以通过不同的形参。重载出不同的函数,这就是多态的特性,但这里多态是编译阶段完成,也就是说编译器会将函数绑定到唯一确定的形式上去,这就是静态多态。

1.2 动态多态

动态多态是通过虚函数和类的继承来实现的。动态多态需要满足如下条件:

  1. 有继承关系;
  2. 子类要重写父类的虚函数(带virtual的函数);
  3. 父类指针指向子类对象;

1.3 虚函数、虚指针、虚表

对于类的成员函数,如果前面加上virtual,那么这个成员函数就是虚函数,这个类就是带有虚函数的类。带有虚函数的类比不带虚函数的类会多一个指针,这个指针就是虚指针,而 虚指针指向一个表,这个表就叫做虚表。虚表里面存的内容就是虚函数的地址。虚表是基于类的,也就是说任何带有虚函数的类都会有一张虚表,这张表是在编译时生成的。而虚指针是基于对象的,当初始化对象时,才会初始化虚指针,这是发生在程序运行时,也是动态多态的关键。

1.4 纯虚函数

纯虚函数是在基类中声明的虚函数,它在基类中是没有定义的,但要求任何派生类都要定义自己的实现方法。在基类中实现纯虚函数的方法是在函数原型后加=0,形如以下格式:

virtual void fun()=0;

  含有纯虚函数的类称之为抽象类,它不能生成对象即创建实列,只能创建它的派生类的实例。抽象类只能作为基类来使用,其纯虚函数的实现由派生类给出。如果派生类中没有重新定义纯虚函数,而只是继承基类的纯虚函数,则这个派生类仍然还是一个抽象类。如果派生类中给出了基类纯虚函数的实现,则该派生类就不再是抽象类了,它是一个可以建立对象的具体的类。

1.5 虚函数和纯虚函数之间的区别

  1. 当基类中的某个成员方法,在大多数情形下都应该由子类提供个性化实现,但基类也可以提供缺省备选方案的时候,该方法应该设计为虚函数。
  2. 当基类中的某个成员方法,必须由子类提供个性化实现的时候,应该设计为纯虚函数。

构造函数和析构函数可以是虚函数吗?

答案是:构造函数不能是虚函数,析构函数可以是虚函数且推荐最好设置为虚函数。

1.6 向上类型转换和向下类型转换

向下类型转换是基类转为派生类的强制类型转换,这种类型转换方式是不安全的;向上类型转换是派生类向基类的类型转换是安全的,如果发生多态,总是安全的。

//向下类型转换 基类转派生类 不安全的
Animal *animal=new Animal;
Cat *cat=(Cat*) animal;

//向上类型转换 派生类转基类 安全的
Cat * cat=new Cat;
Animal *ani=(Aniaml *) cat;

//如果发生多态 总是安全的
Animal *animal=new Cat;
Cat *cat=(Cat *)animal;

2.例子

地址早绑定

#include <iostream>
using namespace std;
//基类 水果类
class Fruit
{
public:
	void getClassName()
	{
		cout << "我是水果类" << endl;
	}

private:

};
//派生类 苹果类
class Apple:public Fruit
{
public:
	void getClassName()
	{
		cout << "我是苹果类" << endl;
	}

private:

};
//地址早绑定 在编译阶段就已经确定了是执行基类的getClassName()函数
void GetClassName(Fruit &fruit) {
	fruit.getClassName();
}
int main()
{
	Apple apple;
	GetClassName(apple);
	return 0;
}

结果

 

地址晚绑定

#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
//基类 水果类
class Fruit
{
public:
	//加上virtual
	virtual void getClassName()
	{
		cout << "我是水果类" << endl;
	}

private:

};
//派生类 苹果类
class Apple:public Fruit
{
public:
	void getClassName()
	{
		cout << "我是苹果类" << endl;
	}

private:

};
//派生类 香蕉类
class Banana :public Fruit
{
public:
	void getClassName()
	{
		cout << "我是香蕉类" << endl;
	}
};
//给父类加上virtual 关键字 地址晚绑定 在运行时再确定调用谁的getClassName()
void GetClassName(Fruit &fruit) {
	fruit.getClassName();
}
int main()
{
	Apple apple;
	Banana banana;
	//GetClassName(apple);
	GetClassName(banana);
	waitKey(10000);
	//return 0;
}

 结果

  • 6
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C++的多性具有静和动两个阶段。在编译时多阶段,多性体现在函数重载和泛型编程方面。通过函数重载,可以使用相同的函数名但不同的参数来重载出不同的函数,这是静性的一种表现。编译器会根据函数的不同参数将其绑定到特定的形式上。在动阶段,多性体现在运行时,具体引用的接口在程序运行时才能确定,这是动性的一种表现。多的字面意思就是多种状,在面向对象的程序设计中,一个接口可以有多种实现方式。C++通过继承、多、虚函数等机制来实现多的概念。因此,C++的多性使得程序可以根据具体的对象类型来调用相应的方法或函数,从而提高代码的灵活性和可复用性。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [C++面试题总结之基础知识点](https://blog.csdn.net/weixin_42060900/article/details/96503788)[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: 50%"] - *2* *3* [C++多理解](https://blog.csdn.net/weixin_44244332/article/details/123507232)[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: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值