C++编程——多态

2023-05-16

文章目录

  • 1. 多态的基本概念
    • 1.1 函数地址早绑定
    • 1.2 地址晚绑定
  • 2. 多态的原理
  • 3. 多态的优点与案例
    • 3.1 多态的优点
    • 3.2 计算器实现案例
  • 4. 纯虚函数与抽象类
  • 5. 虚析构与纯虚析构
    • 5.1 虚析构实现
    • 5.2 纯虚析构实现

多态的知识结构
在这里插入图片描述

1. 多态的基本概念

多态是C++面向对象三大特性之一
多态分为两类

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

静态多态和动态多态的区别

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

1.1 函数地址早绑定

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

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


//执行说话的函数
void doSpeak(Animal &animal)
{
	animal.speak();
}

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


int main()
{
	test01();
	system("pause");
	return 0;
}

运行结果:
在这里插入图片描述
运行结果与我们的意愿不同,我们创建了一个Cat类的对象,希望doSpeak函数能执行Cat类中的speak函数,然而却执行了Animal类中的speak函数。
原因:因为上述代码的doSpeak函数地址在编译阶段就确定了。所以当传进来Cat类的对象时,编译器会做类型转换,认为Cat是动物,所以去执行Animal类中的speak函数。

1.2 地址晚绑定

为了实现传入猫对象,就让猫说话;传入狗对象,就让狗说话的目的,就需要用到动态多态的技术。

//动物类
class Animal
{
public:
	//虚函数
	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();
}

void test01()
{
	Cat cat;
	doSpeak(cat);  //Animal* const animal = &cat; 父类指针或者引用指向子类对象

	Dog dog;
	doSpeak(dog);
}


int main()
{
	test01();
	system("pause");
	return 0;
}

运行结果:
在这里插入图片描述
原因:因为引入了虚函数,上述代码的doSpeak函数地址无法在编译阶段确定,而是在运行阶段确定,也就可以实现动态多态的技术。由上述代码可得动态多态的几个重要问题。

动态多态满足的条件

  1. 有继承关系
  2. 子类重写父类的虚函数(注意重写和重载的区别,重写要求函数返回值类型、函数名、参数列表完全相同)

动态多态的使用
父类指针或者引用指向子类对象

2. 多态的原理

首先来看父类不采用虚函数的对象模型

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

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

调用开发者工具:
在这里插入图片描述
在这里插入图片描述
对于父类来说,因为非静态成员函数不在类中,此时的类为空类只有一个字节。

接着将类中的非静态成员函数改成虚函数的形式

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

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

再次调用开发者工具:
在这里插入图片描述
在这里插入图片描述

发现此时父类和子类均占用4个字节的大小。因为此时类中多了一个vfptr(虚函数指针),虚函数指针指向vftable(虚函数表),对于动物类,其虚函数中存放的是Animal::speak函数的地址。对于狗类,其虚函数中存放的是Dog::speak函数的地址。
看到这里是不是似曾相识?是的,在之前C++编程——继承的菱形继承中也有类似的技术,当时是vbptr(虚基类)和vbtable(虚基类表)的概念。

上述的例子是为了让大家看到,在类中将普通的非静态成员函数改成虚函数之后,类的对象模型发生了改变。那么利用这种新的结构如何实现多态呢?下面将结合代码和图形一起看看。
代码

//执行说话的函数
void doSpeak(Animal &animal)
{
	animal.speak();
}

void test01()
{
	Dog dog;
	doSpeak(dog);
}

利用test01()中的函数执行流程说明多态原理

  1. Dog dog;创建了一个对象

  2. doSpeak(dog);执行
    进行函数参数的传递,Animal &animal = dog,父类的引用指向子类对象
    请添加图片描述执行完上述操作后,animal对象虚函数表中的内容被dog对象虚函数表中的内容所覆盖,得到:
    请添加图片描述

  3. 调用animal.speak();
    由于animal对象的虚函数表中是Dog::speak函数,所以执行的也是Dog类的speak函数,即实现了动态多态

3. 多态的优点与案例

3.1 多态的优点

  1. 组织结构清晰
  2. 可读性强
  3. 对于前期和后期扩展以及维护性高

3.2 计算器实现案例

利用普通写法实现计算器类

//普通写法
class Calculator
{
public:
	int getResult(string oper)
	{
		if (oper == "+")
		{
			return m_Num1 + m_Num2;
		}
		else if (oper == "-")
		{
			return m_Num1 - m_Num2;
		}
		else if (oper == "*")
		{
			return m_Num1 * m_Num2;
		}
		// 如果想扩展新的功能,需要修改源码
		// 真正开发中提倡开闭原则,即对扩展进行开放,对修改进行关闭
	}

	int m_Num1;
	int m_Num2;
};

void test01()
{
	Calculator c;
	c.m_Num1 = 10;
	c.m_Num2 = 10;
	cout << c.m_Num1 << "+" << c.m_Num2 << "=" << c.getResult("+") << endl;
	cout << c.m_Num1 << "-" << c.m_Num2 << "=" << c.getResult("-") << endl;
	cout << c.m_Num1 << "*" << c.m_Num2 << "=" << c.getResult("*") << endl;
}

利用多态实现计算器类

// 利用多态来实现计算器
// 实现计算器抽象类
class AbstractCalculator
{
public:
	virtual int getResult()
	{
		return 0;
	}
	int m_Num1;
	int m_Num2;
};

// 加法计算器类
class AddCalculator:public AbstractCalculator
{
public:
	int getResult()
	{
		return m_Num1 + m_Num2;
	}
};


// 减法计算器类
class SubCalculator :public AbstractCalculator
{
public:
	int getResult()
	{
		return m_Num1 - m_Num2;
	}
};

// 乘法计算器类
class MulCalculator :public AbstractCalculator
{
public:
	int getResult()
	{
		return m_Num1 * m_Num2;
	}
};


void test02()
{
	// 加法运算
	AbstractCalculator *abc = new AddCalculator;
	abc->m_Num1 = 10;
	abc->m_Num2 = 10;
	cout << abc->m_Num1 << "+" << abc->m_Num2 << "=" << abc->getResult() << endl;
	// 用完后销毁堆区数据
	delete abc;


	// 减法运算
	abc = new SubCalculator;
	abc->m_Num1 = 10;
	abc->m_Num2 = 10;
	cout << abc->m_Num1 << "-" << abc->m_Num2 << "=" << abc->getResult() << endl;
	delete abc;

	// 乘法运算
	abc = new MulCalculator;
	abc->m_Num1 = 10;
	abc->m_Num2 = 10;
	cout << abc->m_Num1 << "*" << abc->m_Num2 << "=" << abc->getResult() << endl;
	delete abc;
}

4. 纯虚函数与抽象类

在多态中,通常父类中虚函数的实现是毫无意义的,主要都是调用子类重写的内容,因此可以将虚函数改为纯虚函数
纯虚函数的语法:virtual 返回值类型 函数名 (参数列表) = 0
当类中有了纯虚函数,这个类也称为抽象类

抽象类的特点

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

纯虚函数与抽象类的案例

// 抽象类
class AbstractDrink
{
public:
	// 煮水
	virtual void Boil() = 0;

	// 冲泡
	virtual void Brew() = 0;

	// 倒入杯中
	virtual void PourInCup() = 0;

	// 加入辅料
	virtual void PutSomething() = 0;

	// 制作饮品
	void makeDrink()
	{
		Boil();
		Brew();
		PourInCup();
		PutSomething();
	}
};

// 制作咖啡
class Coffee : public AbstractDrink
{
	// 煮水
	virtual void Boil()
	{
		cout << "煮农夫山泉" << endl;
	}

	// 冲泡
	virtual void Brew()
	{
		cout << "冲泡咖啡" << endl;
	}

	// 倒入杯中
	virtual void PourInCup()
	{
		cout << "倒入杯中" << endl;
	}

	// 加入辅料
	virtual void PutSomething()
	{
		cout << "加入糖和牛奶" << endl;
	}
};


// 制作茶叶
class Tea : public AbstractDrink
{
	// 煮水
	virtual void Boil()
	{
		cout << "煮矿泉水" << endl;
	}

	// 冲泡
	virtual void Brew()
	{
		cout << "冲泡茶叶" << endl;
	}

	// 倒入杯中
	virtual void PourInCup()
	{
		cout << "倒入杯中" << endl;
	}

	// 加入辅料
	virtual void PutSomething()
	{
		cout << "加入柠檬" << endl;
	}
};

//制作函数
void doWork(AbstractDrink &a)
{
	a.makeDrink();
}

void test01()
{
	Coffee coffee;
	Tea tea;
	//制作咖啡
	doWork(coffee);
	cout << "-----------------" << endl;
	//制作茶叶
	doWork(tea);
}

5. 虚析构与纯虚析构

先来看一段代码:

//动物类
class Animal
{
public:
	Animal()
	{
		cout << "Animal的构造函数调用" << endl;
	}

	~Animal()
	{
		cout << "Animal的析构函数调用" << endl;
	}

	//纯虚函数
	virtual void speak() = 0;
	
};

//猫类
class Cat : public Animal
{
public:
	Cat(string name)
	{
		cout << "Cat的构造函数调用" << endl;
		m_Name = new string(name);
	}

	~Cat()
	{
		if (m_Name != NULL)
		{
			cout << "Cat的析构函数调用" << endl;
			delete m_Name;
			m_Name = NULL;
		}
	}

	void speak()
	{
		cout << *m_Name <<"小猫在说话" << endl;
	}
	string *m_Name;
};



//执行说话的函数
void doSpeak(Animal &animal)
{
	animal.speak();
}

void test01()
{
	Animal* animal = new Cat("加菲");
	animal->speak();
	delete animal;
}


int main()
{
	test01();
	system("pause");
	return 0;
}

运行结果:
在这里插入图片描述
可以看到Cat类的析构函数并没有被调用,这就出现了问题。即多态使用时,如果子类中有属性开辟到堆区,那么父类指针在析构的时候,不会调用子类中的析构函数,会出现内存泄漏。

解决方式:将父类中的析构函数改为虚析构或者纯虚析构
虚析构语法virtual ~类名(){}
纯虚析构语法virtual ~类名() = 0 类名::~类名(){}

5.1 虚析构实现

//动物类
class Animal
{
public:
	Animal()
	{
		cout << "Animal的构造函数调用" << endl;
	}

	virtual ~Animal()
	{
		cout << "Animal的析构函数调用" << endl;
	}

	//纯虚函数
	virtual void speak() = 0;
	
};

5.2 纯虚析构实现

错误代码

//动物类
class Animal
{
public:
	Animal()
	{
		cout << "Animal的构造函数调用" << endl;
	}

	virtual ~Animal() = 0;

	//纯虚函数
	virtual void speak() = 0;
	
};

上述代码会报错,因为考虑到父类如果有数据开辟到堆区也应当需要析构代码进行释放,所以必须提供纯虚析构函数的具体实现。
正确代码

//动物类
class Animal
{
public:
	Animal()
	{
		cout << "Animal的构造函数调用" << endl;
	}

	virtual ~Animal() = 0;

	//纯虚函数
	virtual void speak() = 0;
	
};
Animal:: ~Animal()
{
	cout << "Animal的纯虚析构函数调用" << endl;
}

总结
虚析构和纯虚析构共性:

  • 可以解决父类指针无法完全释放子类对象的问题
  • 都需要有具体的函数实现

虚析构和纯虚析构区别:

  • 如果是纯虚析构,该类属于抽象类,无法实例化对象
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++编程——多态 的相关文章

  • CocoaPods的使用——pod install pod install --repo-update pod update pod update --repo-update

    Podfile文件中 xff0c 使用某个库时 不指定版本 xff0c 表示希望使用最新版本 xff0c 如 pod SDWebImage 指定明确版本 xff0c 表示只想要这个版本 xff0c 如 xff1a pod 39 SDWebI
  • SceneDelegate有什么作用?删除有什么影响

    自从Xcode11发布以来 xff0c 当你使用新XCode创建一个新的iOS项目时 xff0c SceneDelegate会被默认创建 xff0c 它到底有什么用呢 xff1f 在iOS 13 xff08 及以后版本 xff09 上 xf
  • UICollectionViewCell自适应宽度

    如图所示效果 xff0c 根据字符长度自适应UICollectionViewCell的大小 xff0c 同时进行左对齐处理 如何实现 继承UICollectionViewFlowLayout创建子类 xff0c 并实现相关的方法 xff0c
  • 微信小程序开发——JS中字符和数组的操作

    字符的操作 span class token keyword var span word span class token operator 61 span span class token string 34 hello world 34
  • 微信小程序开发——字体样式设置

    font style文字样式 normal 正常字体italic 斜体字oblique 倾斜字体 font weight文字粗细 取值范围 100 900normal 相当于400bold 粗体 相当于700bolderlighter fo
  • 异常处理——richview不显示cloud路径的图片

    图片上传后 xff0c 得到的文件路径为cloud xxx png格式 xff0c 使用image组件时 xff0c 正常显示 xff0c 但使用richview富文本组件时 xff0c 未显示出来 此时 xff0c 需要通过使用wx cl
  • 编译错误“Too many arguments to function call....”

    运行编译过程中出现错误 xff0c 并提示 Too many arguments to functions call expected 的信息 xff0c 如图一 遇到这种情况时 xff0c 该如何解决呢 xff1f 解决方法是将属性 En
  • CocoaPods的使用——cocoapods的升级更新

    最近使用cocoa pods时提示版本过低需要升级才能正常使用 但是在升级过程中又出现了问题 首先我是直接使用语句 xff1a sudo gem install cocoapods 进行更新升级的 xff0c 没想到又报错了 接着我在想是不
  • http请求方法(GET、POST、HEAD、OPTIONS、PUT、DELETE、TRACE、CONNECT)

    根据HTTP标准 xff0c HTTP请求可以使用多种请求方法 HTTP的1 0版本中只有三种请求方法 xff1a GET POST 和 HEAD方法 到了1 1版本时 xff0c 新增加了五种请求方法 xff1a OPTIONS PUT
  • MongoDB可视化工具 Studio 3T

    告别终端使用可视化工具Studio 3T对MongoDB进行数据库的操作 简单的使用步骤介绍 1 启动MongoDB服务器 xff08 方法见MongoDB介绍与安装中的介绍 xff09 2 连接MongoDB服务器 3 操作数据库
  • 微信小程序开发——form表单

    WeChat小程序交流 xff08 QQ群 xff1a 769977169 xff09 效果图 代码示例 1 xxx wxml lt form bindsubmit 61 39 submitClick 39 bindreset 61 39
  • 苹果电脑(Mac mini或Macbook或iMac)恢复出厂设置

    苹果电脑 xff08 Mac mini或Macbook或iMac xff09 恢复出厂设置 xff0c 首先要做好如下的准备 xff1a 第一 xff1a 数据的备份 xff1b 第二 xff1a 保证正常的wifi连接 xff1b 第三
  • VSLAM基础(一)————常见特征点提取算法及匹配优化

    过年期间闲来无事 xff0c 就想来把这半年学习的一些视觉知识 xff08 视觉slam相关 xff09 做个梳理 xff0c 就以这篇图像特征点提取与匹配作为开头吧 一 关键点与描述子 关键点 xff1a 图像上某些特殊的 具有代表的点
  • 【2017CS231n】第十五讲:神经网络模型压缩和加速(硬件、算法层面)

    一 算法 1 剪枝 不是所有的神经网络连接都有用 减少连接 xff0c 但不降低准确性 尝试性 xff1a 剪枝 xff0c 训练不断重复 xff0c 找到对准确性影响最高的那一部分连接 2 参数共享 1 98 2 09 1 92 1 87
  • 程序员面试等通知一般多久?

    最近面试的人比较多 xff0c 毕竟是金三银四嘛 xff0c 竞争也挺大的 xff0c 很多人在面试之后 xff0c 久久没有收到入职通知 xff0c 等待是一件非常痛苦的事情 那么程序员面试等通知一般多久 xff1f 多久没有发通知就等于
  • 程序员简历项目经验怎么写?

    我是一个典型的互联网公司程序员 xff0c 也见过无数的程序员简历 xff0c 包括很多优秀的程序员简历 xff0c 看了可以让人眼前一亮 xff0c 优美简洁的简历模板 xff0c 项目经验工作重点突出 也见过更多的写得不好的简历 程序员
  • OpenRAVE

    机器人的高级功能 机械手臂控制 软件方面 在ros里 有moveit 研究的过程中 扩展到了openrave专业包 Welcome to OpenRAVE Latest Official Release 0 8 2 OpenRAVE pro
  • C++——STL初识

    一 为什么需要STL xff1f 目的 xff1a 为了建立一套重复利用的东西 使用STL可以避免从事大量重复的工作 为建立数据结构的一套标准 xff0c 诞生了STL 二 基本概念 STL是标准模板库 STL从广义上分为 xff1a 容器
  • Showing progress bar in a status bar pane

    This article was contributed by Brad Mann This code creates a progress bar anywhere in the status window and the control
  • 大小端字节序转换

    特点 各主机的字节序可能不同 xff0c 网络协议指定的通讯字节序为大端 只有在多字节数据处理时才需要考虑字节序 运行在同一台计算机的进程互相通信时 xff0c 不需要考虑字节序 二 字节序转换函数 头文件 xff1a include lt

随机推荐

  • 51单片机控制0.96寸OLED(IIC接口)

    1 OLED初步认识 OLED Organic Light Emitting Diode xff0c 即有机发光二极管 OLED由于同时具备自发光 xff0c 不需背光源 xff0c 对比度高 xff0c 厚度薄 xff0c 视角广 xff
  • 51单片机控制LCD1602模块

    51单片机控制LCD1602模块 视频播放 xff1a LCD1602视频 xff08 1 xff09 LCD1602概述 先来看看LCD1602什么意思 xff1f Liquid Crystal Display LCD 表示液晶显示 xf
  • LCD1602模块如何显示自定义字符

    相信大家现在知道了如何通过查字库表的方法来显示表中的任意一个字符 假如现在我想显示某个温度值 xff0c 需要标志出温度符号 C xff0c 现在你去字库表里面查找 xff0c 发现根本找不到这个符号 xff0c 那怎么办 xff1f 下面
  • 51单片机控制温度传感器DS18B20

    xff08 1 xff09 DS18B20初步认识 DS18B20是美国DALLAS半导体公司推出的一种数字化单总线器件 xff0c 属于新一代适配微处理器的改进型智能温度传感器 我们先来看看DS18B20在芯片手册上的标题 DS18B20
  • ESP8266模块手机端和电脑端网络调试助手

    ESP8266模块手机端和电脑端网络调试助手 使用方法比较简单 xff0c 如下界面所示 xff1a 电脑端 xff1a 确定 协议类型 xff0c 34 IP地址 34 和 34 端口 34 xff0c 然后点击连接即可 xff0c 如下
  • Micro Python 入门教程-pyboard V1.1控制LCD1602液晶显示模块

    11 LCD1602液晶显示模块 11 1 初识LCD1602液晶模块 LCD1602什么意思 xff0c LCD表示Liquid Crystal Display xff0c 1602表示一行可以显示16个字符 xff0c 一共有两行 实物
  • 常见无人机自组网路由协议

    常见无人机自组网路由协议 无人机自组网路由协议静态路由协议先验式路由协议反应式路由协议 无人机自组网路由协议 为了适应无人机组网节点高速移动带来的网络拓扑结构快速变化 xff0c 无人机自组网使用的路由协议主要有以下几种 静态路由协议 这种
  • 尚硅谷大数据项目之Flink实时数仓-踩坑记录和笔记记录

    这里写自定义目录标题 1 关于Slf4j注解配置文件logback xml不生效问题2 判断新老用户的时候 xff0c 什么时候会出问题 xff1a 3 为什么维度数据选择存储在Hbase中 xff0c 而不是Redis xff0c Mys
  • 【学习笔记】尚硅谷大数据项目之Flink实时数仓---数据可视化接口实现

    这里写自定义目录标题 第 1 章 数据可视化接口1 1 设计思路1 2 需求梳理1 2 1 最终显示效果图1 2 2 分析可视化大屏1 2 3 接口执行过程 第 2 章 Sugar 数据大屏2 1 产品介绍2 2 使用入口2 3 创建数据大
  • VR发展前景展望

    VR发展前景展望 引子 随着计算机技术的飞速发展 xff0c 虚拟现实也在短时间内经历了萌芽探索到飞速发展完善的转变 由于其独特的沉浸式体验 xff0c VR的前景被大多数人看好 xff0c 更多的VR相关技术也在为让人能更完美的融合到这个
  • Ubuntu18.04下C++分文件编写报错:对‘Class::Func()’未定义的引用解决办法

    源代码结构 如图所示 xff0c 编写一个员工管理系统 xff0c 在WorkerManager h中声明类和函数 xff0c 在WorkerManager cpp中写具体实现在staffManagementSystem cpp中实例化类
  • 人工智能是什么?

    人工智能是什么 xff1f 欢迎大家迈入人工智能的大门1 人工智能的定义2 人工智能的话题3 人工智能的四大技术分支4 人工智能的主要应用领域5 人工智能的三种形态5 1 弱人工智能到强人工智能有多难 xff1f 5 2 弱人工智能的前进方
  • 浏览器-基本认证(Basic Authentication)-摘要认证(digest authentication)=spring boot实现demo

    平时开发的 java web 网站登录 xff0c 都是通过表单提交登录信息 有时一些中间件登录是浏览器弹窗 xff0c 没有看到表单实现代码 故通过查询 xff0c 发现两种 HTTP 简单认证 xff1a 基本认证 Basic Auth
  • PX4 gazebo仿真 2023.4.13更新

    前言 想实现px4仿真 xff0c 考虑使用gazebo仿真 去PX4官网看一眼先 xff0c 官网提到后面如果要用ROS xff0c 直接配置ROS就好了 xff0c 不然会不兼容 xff0c 那么就按官网步骤走 官网步骤 结果第一步就失
  • PX4 & gazebo仿真 offboard模式无法起飞解决思路

    前言 我用最新版PX4固件 xff0c offboard模式飞机无法起飞 xff0c 网上有一种说法是固件版本的问题 xff0c 让用旧一点的版本 添加链接描述 这个链接描述的情况和我的一模一样 xff0c 所以我肯定是按这个方法尝试的 旧
  • 数字图传VS模拟图传 图传技术知识 2023.3.6更新

    引言 在研究无人机小半年了 xff0c 多次听到数字图传和模拟图传字眼 xff0c 一直都是一知半解 xff0c 这次整体了解一下并加以 整理 数字图传 数字图传 xff1a 指数字化的图像信号经信源编码和信道编码 xff0c 通过数字信道
  • 069-线性系统的可控性和可观测性

    对一个线性系统 xff0c 需要判定其可控性或者可观测性 xff0c 才能对其进行求解 或者说的狭义一点 xff0c 在一个卡尔曼滤波模型中 xff0c 只有判定了其可控性 xff0c 才能知晓状态向量X中多少个状态是可观测的 比如X中原有
  • 滴水石穿

    不积跬步 xff0c 无以至千里 xff1b 不积小流 xff0c 无以成江海 1 hashcode相等两个类一定相等吗 equals呢 相反呢 hashcode相等 xff0c 两个类不一定相等 xff1b equals相等 xff0c
  • C++编程——友元

    文章目录 1 友元的概念2 友元的三种实现2 1 全局函数做友元2 2 类做友元2 3 成员函数做友元 1 友元的概念 友元目的是让一个函数或者类访问另一个类中的私有成员 有一个非常生动的例子 xff0c 就是家中会有客厅和卧室 xff0c
  • C++编程——多态

    文章目录 1 多态的基本概念1 1 函数地址早绑定1 2 地址晚绑定 2 多态的原理3 多态的优点与案例3 1 多态的优点3 2 计算器实现案例 4 纯虚函数与抽象类5 虚析构与纯虚析构5 1 虚析构实现5 2 纯虚析构实现 多态的知识结构