前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【C++】泛型编程 ⑨ ( 类模板的运算符重载 - 函数声明 和 函数实现 写在同一个类中 | 类模板 的 外部友元函数问题 )

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

作者头像
韩曙亮
发布2023-11-22 12:45:53
2350
发布2023-11-22 12:45:53
举报
文章被收录于专栏:韩曙亮的移动开发专栏

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


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

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

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

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

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

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

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

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

代码语言:javascript
复制
// 声明 类模板 父类
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& 类型的 , 如果定义在了 类内部 , 左操作数就默认为当前类 ;

代码示例 :

代码语言:javascript
复制
#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;
}

执行结果 :

代码语言:javascript
复制
10
666
88
66
Press any key to continue . . .
在这里插入图片描述
在这里插入图片描述

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


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

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

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

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

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

在这里插入图片描述
在这里插入图片描述

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

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

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

代码示例 :

代码语言:javascript
复制
#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;
}

执行结果 :

代码语言:javascript
复制
a = 666 , b = 888
a = 222 , b = 111
a = 888 , b = 999
a:888 b: 999

Press any key to continue . . .
在这里插入图片描述
在这里插入图片描述
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-11-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、类模板 - 函数声明与函数实现分离
    • 1、函数声明与函数实现分离
      • 2、代码示例 - 函数声明与函数实现分离
        • 3、函数声明与函数实现分离 + 友元函数引入
        • 二、普通类的运算符重载 - 函数声明 和 函数实现 写在同一个类中
        • 三、类模板的运算符重载 - 函数声明 和 函数实现 写在同一个类中
          • 1、类模板 的 外部友元函数问题
            • 2、代码示例 - 类模板 函数声明 和 函数实现 写在同一个类中 ( 包括友元函数 )
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档