【C++】泛型编程 ⑨ ( 类模板的运算符重载 - 函数声明 和 函数实现 写在同一个类中 | 类模板 的 外部友元函数问题 )

news2024/11/15 11:58:39

文章目录

  • 一、类模板 - 函数声明与函数实现分离
    • 1、函数声明与函数实现分离
    • 2、代码示例 - 函数声明与函数实现分离
    • 3、函数声明与函数实现分离 + 友元函数引入
  • 二、普通类的运算符重载 - 函数声明 和 函数实现 写在同一个类中
  • 三、类模板的运算符重载 - 函数声明 和 函数实现 写在同一个类中
    • 1、类模板 的 外部友元函数问题
    • 2、代码示例 - 类模板 函数声明 和 函数实现 写在同一个类中 ( 包括友元函数 )






一、类模板 - 函数声明与函数实现分离




1、函数声明与函数实现分离


项目开发中 , 需要 将 函数声明 与 函数实现 分开进行编码 ;


将 函数声明 与 函数实现 分开进行编码 , 有 三种 方式 :

  • 类模板 的 函数声明 与 函数实现 都写在同一个类中 ;
  • 类模板 的 函数实现 在 类外部进行 , 写在相同的 .h 和 .cpp 源码文件中 ;
  • 类模板 的 函数实现 在 类外部进行 , 写在不同的 .h 和 .cpp 源码文件中 ;

2、代码示例 - 函数声明与函数实现分离


对于下面的 Father 类中的 printValue 函数 ,

// 声明 类模板 父类
template <typename T>
class Father {
public:
    T value;
    Father(T val) : value(val) {}
    void printValue() {
        std::cout << value << std::endl;
    }
};

如果要在外部 实现 printValue 的话 , 写法如下 :

// 声明 类模板 父类
template <typename T>
class Father {
public:
    T value;
    Father(T val) : value(val) {}
    void printValue();
};

// 在 类模板 外部实现函数
template <typename T>
void Father<T>::printValue()
{
    std::cout << value << std::endl;
}

每个函数前面都要加上 template <typename T> 类型参数列表声明 ,

使用域作用符 Father<T>:: 访问函数 ;


3、函数声明与函数实现分离 + 友元函数引入


如果要在 类模板 中进行运算符重载 , 就需要用到友元函数 ;

如果将 类模板 的 函数实现 , 定义在函数外部 , 结合 友元函数 使用 , 就变得很复杂 , 下面针对该问题进行讨论 ;





二、普通类的运算符重载 - 函数声明 和 函数实现 写在同一个类中



下面的类是一个 普通类 , 其中定义了 成员变量 和 成员方法 ;

并为其重载了 左移运算符 和 加法运算符 ;

其中 加法运算符 重载 是在 类内部实现的 ,

左移运算符 重载 是在类外部 通过友元函数实现的 , 因为左移运算符的 左操作数是 ostream& 类型的 , 如果定义在了 类内部 , 左操作数就默认为当前类 ;


代码示例 :

#include "iostream"
using namespace std; 

class Student
{
	// 左移运算符重载
	friend ostream& operator<<(ostream& out, Student& s)

public:
	Student(int x = 0, int y = 0)
	{
		this->a = x;
		this->b = y;
	}

	// 重载 + 运算符
	Student operator+(Student& s)
	{
		Student student(this->a + s.a, this->b + s.b);
		return student;
	}

	// 打印类成员变量
	void printStudent()
	{
		cout << "a = " << a << " , b = " << b << endl;
	}

public:
	int a, b;
};

// 重载左移运算符
ostream& operator<<(ostream& out, Student& s)
{
	out << "a:" << s.a << " b: " << s.b << endl;
	return out;
}

int main() {
	Student s(666, 888);
	s.printStudent();
	
	// 控制台暂停 , 按任意键继续向后执行
	system("pause");

	return 0;
}

执行结果 :

10
666
88
66
Press any key to continue . . .

在这里插入图片描述





三、类模板的运算符重载 - 函数声明 和 函数实现 写在同一个类中




1、类模板 的 外部友元函数问题


将上述 " 普通类的运算符重载 - 函数声明 和 函数实现 写在同一个类中 " 示例改造成 类模板 示例 ;

问题就出现在 定义在外部的 友元函数 中 ,

友元函数 , 不能 读取 和 访问 到 泛型类型 T , 也就是 类模板 中 的 template <typename T> 泛型类型 T ;

在外部重新定义 template <typename T> 就是重新定义了一个新的泛型 , 与 类模板 中的 T 不是同一个泛型类型 ;

在这里插入图片描述

解决上述问题 , 就需要将 友元函数 定义在 类模板 的内部 ;

template <typename T>
class Student
{
	// 左移运算符重载
	friend ostream& operator<<(ostream& out, Student& s2)
	{
		out << "a:" << s.a << " b: " << s.b << endl;
		return out;
	}
}

2、代码示例 - 类模板 函数声明 和 函数实现 写在同一个类中 ( 包括友元函数 )


代码示例 :

#include "iostream"
using namespace std; 

template <typename T>
class Student
{
	// 左移运算符重载
	friend ostream& operator<<(ostream& out, Student& s)
	{
		out << "a:" << s.a << " b: " << s.b << endl;
		return out;
	}

public:
	Student(T x, T y)
	{
		this->a = x;
		this->b = y;
	}

	// 重载 + 运算符
	Student operator+(Student& s)
	{
		Student student(this->a + s.a, this->b + s.b);
		return student;
	}

	// 打印类成员变量
	void printStudent()
	{
		cout << "a = " << a << " , b = " << b << endl;
	}

public:
	T a, b;
};

// 重载左移运算符
//ostream& operator<<(ostream& out, Student& s)
//{
//	out << "a:" << s.a << " b: " << s.b << endl;
//	return out;
//}

int main() {
	// 模板类不能直接定义变量
	// 需要将 模板类 具体化之后才能定义变量
	Student<int> s(666, 888);
	s.printStudent();

	Student<int> s2(222, 111);
	s2.printStudent();

	// 验证 加法运算符 + 重载
	Student<int> s3 = s + s2;
	s3.printStudent();

	// 验证 左移运算符 << 重载
	cout << s3 << endl;
	
	// 控制台暂停 , 按任意键继续向后执行
	system("pause");

	return 0;
}

执行结果 :

a = 666 , b = 888
a = 222 , b = 111
a = 888 , b = 999
a:888 b: 999

Press any key to continue . . .

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1234772.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

AMEYA360:蔡司扫描电镜Sigma系列:扫描电子显微镜的用途原来这么多

扫描电子显微镜是一种全自动的、非破坏性的显微分析系统&#xff0c;可针对无机材料和部分有机材料&#xff0c;迅速提供在统计学上可靠且可重复的矿物学、岩相学和冶金学数据&#xff0c;在采矿业&#xff0c;可用于矿产勘查、矿石表征和选矿工艺优化&#xff0c;在石油和天然…

Oracle数据库笔记(一)

1.概述 Oracle版本 19c 在线迁移、自适应扫描、自适应数据共享11g 企业管理器、自动化诊断工具、自动化性能管理 Oracle特点 可用性强可扩展性强数据安全性强稳定性强 常见数据库 小 Access中 SQL Server、MySQL大 Oracle、DB2 2.数据、数据库、数据库管理系统、数据库系…

【项目管理】甘特图(1)——认识甘特图

哈喽&#xff0c;大家好&#xff0c;我是雷工&#xff01; 今天学习下甘特图的绘制&#xff0c;以下为学习笔记。 一、什么是甘特图 甘特图是可以直观展示项目进展随时间走势和联系的条状图。是一种常见的项目管理工具。 项目的时间用横轴表示&#xff0c;项目的进度用纵轴表…

vue diff算法原理以及v2v3的区别

diff算法简介 diff算法的目的是为了找到哪些节点发生了变化&#xff0c;哪些节点没有发生变化可以复用。如果用最传统的diff算法&#xff0c;如下图所示&#xff0c;每个节点都要遍历另一棵树上的所有节点做比较&#xff0c;这就是o(n^2)的复杂度&#xff0c;加上更新节点时的…

可视化大屏时代的到来:智慧城市管理的新思路

随着科技的不断发展&#xff0c;智能芯片作为一种新型的电子元件&#xff0c;被广泛应用于各个领域&#xff0c;其中智慧芯片可视化大屏是一种重要的应用形式。 一、智慧芯片可视化大屏的优势 智慧芯片可视化大屏是一种将智能芯片与大屏幕显示技术相结合的产品&#xff0c;山海…

算法分析与设计课后练习23

求下面的0-1背包问题 &#xff08;1&#xff09;N5,M12,(p1,p2,…,p5)(10,15,6,8,4),(w1,w2,…,w5)(4,6,3,4,2) &#xff08;2&#xff09;N5,M15,(p1,p2,…,p5)(w1,w2,…,w5)(4,4,5,8,9)

Springboot+vue的社区医院管理系统(有报告),Javaee项目,springboot vue前后端分离项目

演示视频&#xff1a; Springbootvue的社区医院管理系统(有报告)&#xff0c;Javaee项目&#xff0c;springboot vue前后端分离项目 项目介绍&#xff1a; 本文设计了一个基于Springbootvue的前后端分离的应急物资管理系统&#xff0c;采用M&#xff08;model&#xff09;V&am…

【Django使用】4大模块50页md文档,第4篇:Django请求与响应和cookie与session

当你考虑开发现代化、高效且可扩展的网站和Web应用时&#xff0c;Django是一个强大的选择。Django是一个流行的开源Python Web框架&#xff0c;它提供了一个坚实的基础&#xff0c;帮助开发者快速构建功能丰富且高度定制的Web应用 Django全套笔记地址&#xff1a; 请移步这里 …

动态规划十大经典问题

动态规划十大经典问题 动态规划十大经典问题 数塔取数问题、矩阵取数问题、最大连续子段和、最长递增子序列、最长公共子序列、最长公共子串、最短编辑距离、背包问题、正整数分组、股票买卖问题。 1、数塔取数问题 // 数塔取数问题 public static int dataTowerAccess(int[]…

一文读懂 Linux 网络 IO 模型

文章目录 1.从一个问题说起2.多进程模型3.多线程模型4.I/O 多路复用5.select、poll、epoll 的区别&#xff1f;5.1 select5.2 poll5.3 epoll5.4 两种事件触发模式 参考文献 1.从一个问题说起 互联网发展历史上&#xff0c;曾经有一个著名的问题&#xff1a;C10K 问题。 C 是 …

5-4计算一串字符的空格数字字符其他

#include<stdio.h> int main(){char c;int space0;//空格int letters0;//英文字母int numbers0;//数字int others0;//其他字符printf("请输入一行字符&#xff1a;");while((cgetchar())!\n)//获取字符的内容&#xff0c;到\n停止{if(c>a&&c<z|…

AR眼镜方案—单目光波导AR智能眼镜

光波导技术是一项具有前沿意义的技术&#xff0c;它能够将光线反射180度&#xff0c;使得眼镜框架内置的MicroLED屏幕的图像通过多次反射与扩散后准确地传递到人眼中。采用MicroLED显示技术的AR智能眼镜不仅体积显著缩小&#xff0c;屏幕只有0.68英寸大小&#xff0c;并且还能够…

【PostgreSQL】解决PostgreSQL时区(TimeZone)问题

问题描述 最近在使用PostgreSQL中&#xff0c;对行记录进行设置创建时间&#xff08;created_time&#xff09;时&#xff0c;出现了设置了now()时间而数据库中写入的数据是不一致的数据。 eg&#xff1a; insert into dept ( created_at, updated_at) VALUES (now(),now())…

Spring框架学习 -- 核心思想

目录 (1) Spring是什么? (2) 什么是IOC容器? (3) 从传统开发认识spring (4) 这种传统开发的缺陷 (5)解决传统开发中的缺陷 (6) 对比总结规律 (7) 理解IOC 创作不易多多支持 (1) Spring是什么? 我们常说的Spring的全称是: Spring Framework(Spring框架), 它是一个开源…

【经验之谈·高频PCB电路设计常见的66个问题】

文章目录 1、如何选择PCB 板材&#xff1f;2、如何避免高频干扰&#xff1f;3、在高速设计中&#xff0c;如何解决信号的完整性问题&#xff1f;4、差分布线方式是如何实现的&#xff1f;5、对于只有一个输出端的时钟信号线&#xff0c;如何实现差分布线&#xff1f;6、接收端差…

微信小程序记住密码,让登录解放双手

密码是用户最重要的数据&#xff0c;也是系统最需要保护的数据&#xff0c;我们在登录的时候需要用账号密码请求登录接口&#xff0c;如果用户勾选记住密码&#xff0c;那么下一次登录时&#xff0c;我们需要将账号密码回填到输入框&#xff0c;用户可以直接登录系统。我们分别…

win11,安装python,pip,和opencv

1,安装python 在应用商店&#xff0c;输入python&#xff0c;下载安装 2&#xff0c;安装pip 在cmd中&#xff0c;输入pip install SomePackage&#xff0c;安装某一个版本的pip 3,安装opencv 在cmd中&#xff0c;输入 pip3 install opencv-contrib-python -i https://pyp…

css 实现鼠标上移添加下划线

效果图 实现代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"widthdevice-wi…

Linux网络驱动

Linux 网络设备驱动结构 网络协议接口层向网络层协议提供统一的数据包收发接口&#xff0c;这一层使得上层协议独立于具体的设备网络设备接口层向协议接口层提供统一的用于描述具体网络设备属性和操作的结构体net_device&#xff0c;该结构体是设备驱动功能层中各函数的容器设备…

力扣C++学习笔记——C++ 给vector去重

要使用std::set对std::vector进行去重操作&#xff0c;您可以将向量中的元素插入到集合中&#xff0c;因为std::set会自动去除重复元素。然后&#xff0c;您可以将集合中的元素重新存回向量中。以下是一个示例代码&#xff0c;演示如何使用std::set对std::vector进行去重&#…