C++模板类的使用以及运算符重载的实现

2023-10-27

一、类模板及运算符重载的实现

如同函数模板一样,使用类模板使用户可以为类定义一种模式,使得类中的某些数据成员、某些成员函数的参数、某些成员函数的返回值能取任意类型。类模板是对一批仅仅成员数据类型不同的类的抽象,程序员只要为这一批类所组成的整个类家族创建一个类模板,给出一套程序代码,就可以用来生成多种具体的类,(这类可以看作是类模板的实例),从而大大提高编程的效率。

 

定义类模板的一般形式是:

template <类型名 参数名1,类型名 参数名2,…>
class 类名
{
  类声明体
};

例如:

template <class T>
class complex{
	T a, b;
	public:
		complex(T, T);
		complex(){}
		void show();
		complex operator +(complex &);    // 声明运算符 ‘+’ 的重载
		complex operator -(complex &);    // 声明运算符 ‘-’ 的重载
};

 

在类模板的外部定义类成员函数的一般形式如下所示:

 

template <类型名 参数名1,类型名 参数名2,…>
函数返回值类型 类名<参数名 1 参数名 2,…>::成员函数名(形参表)
{
  函数体
}

例如:

template <class T>
complex<T> complex<T>::operator+(complex<T> &x1)
// 注意在模板类外部进行定义时,返回值以及形参的类型都需要为 complex<T>,而不能是 complex
{
	return complex(a+x1.a, b+x1.b);
}

类模板是一个类家族的抽象,它只是对类的描述,编译程序不为类模板(包括成员函数定义)创建程序代码,但是通过对类模板的实例化可以生成一个具体的类以及该具体类的对象。

与函数模板不同的是:函数模板的实例化是由编译程序在处理函数调用时自动完成的,而类模板的实例化必须由程序员在程序中显式地指定,其实例化的一般形式是:

类名 <数据类型 1(或数据),数据类型 2(或数据)…> 对象名

例如:

complex<int> c1(1,2);         // 要根据自己定义的构造函数来确定是否添加参数

完整代码如下所示:

#include <iostream>
using namespace std;

template <class T>
class complex{
	T a, b;
	public:
		complex(T, T);
		complex(){}
		void show();
		complex operator +(complex &);
		complex operator -(complex &);
};

template <class T>
complex<T>::complex(T x, T y):a(x), b(y){cout<<"Have create the complex!"<<endl;}

template <class T>
void complex<T>::show()
{
	cout<<a<<'+'<<b<<'i'<<endl;
}

template <class T>
complex<T> complex<T>::operator+(complex<T> &x1)
{
	return complex(a+x1.a, b+x1.b);
}

template <class T>
complex<T> complex<T>::operator-(complex<T> &x2)
{
	return complex(a-x2.a, b-x2.b);
}

void main()
{
	complex<int> c1(1,2);
	complex<int> c2(2,3);
	complex<int> c3 = c1+c2;
	complex<int> c4 = c2-c1;

	c1.show();
	c3.show();
	c4.show();
}

二、用友元函数实现运算符重载

关于友元函数有以下几点说明:

1)C++中引入友元函数,是为在该类中提供一个对外(除了他自己意外)访问的窗口;
2)这个友元函数他不属于该类的成员函数,他是定义在类外的普通函数,只是在类中声明该函数可以直接访问类中的private或者protected成员。

使用友元函数实现运算符重载如下所示:

#include "stdafx.h"


#include <iostream>
using namespace std;

template <class T>
class complex {
	T a, b;
public:
	complex(T, T);
	complex() {};
	void show();

	template <class T1>
	friend complex<T1> operator *(const complex<T1> &, const complex<T1> &);
};

template <class T>
complex<T>::complex(T x, T y) :a(x), b(y) { cout << "Have create the complex!" << endl; }

template <class T>
void complex<T>::show()
{
	cout << a << '+' << b << 'i' << endl;
}

template <class T1>
complex<T1> operator *(const complex<T1> &c1, const complex<T1> &c2)     // 由于友元函数不属于类,所以在定义时不需要说明该函数属于类
{
	T1 real = c1.a*c2.a - c1.b*c2.b;
	T1 ima = c1.a*c2.b + c2.a*c1.b;
	return complex<T1>(real, ima);
}

void main()
{
	complex<int> c1(1, 2);
	complex<int> c2(2, 3);
	complex<int> c3 = c1*c2;
	c3.show();
	system("pause");
}

 

 

 

 

 

 

 

 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++模板类的使用以及运算符重载的实现 的相关文章

  • C++ 维护子类对象的混合集合

    如果我在这里错过了一个相当基本的概念 我很抱歉 但我正在尝试弄清楚如何维护多个类类型的集合 所有类类型都派生自同一个父类 并且在检索它们时仍然可以访问它们的特定于子类的方法从集合中 作为上下文 我有一个基类 BaseClass 和许多类 例
  • 适合初学者的良好调试器教程[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 有谁知道一个好的初学者教程 在 C 中使用调试器 我感觉自己好像错过了很多 我知道怎么做 单步执行代码并查看局部变量 虽然这常常给我带来问
  • 如何在多线程C++ 17程序中交换两个指针?

    我有两个指针 pA 和 pB 它们指向两个大的哈希映射对象 当pB指向的哈希图完全更新后 我想交换pB和pA 在C 17中 如何快速且线程安全地交换它们 原子 我是 c 17 的新手 2个指针的原子无等待交换可以通过以下方式实现 inclu
  • 在c#中执行Redis控制台命令

    我需要从 Redis 控制台获取 客户端列表 输出以在我的 C 应用程序中使用 有没有办法使用 ConnectionMultiplexer 执行该命令 或者是否有内置方法可以查找该信息 CLIENT LIST是 服务器 命令 而不是 数据库
  • 如何在C(Linux)中的while循环中准确地睡眠?

    在 C 代码 Linux 操作系统 中 我需要在 while 循环内准确地休眠 比如说 10000 微秒 1000 次 我尝试过usleep nanosleep select pselect和其他一些方法 但没有成功 一旦大约 50 次 它
  • 查找进程的完整路径

    我已经编写了 C 控制台应用程序 当我启动应用程序时 不使用cmd 我可以看到它列在任务管理器的进程列表中 现在我需要编写另一个应用程序 在其中我需要查找以前的应用程序是否正在运行 我知道应用程序名称和路径 所以我已将管理对象搜索器查询写入
  • 如何判断计算机是否已重新启动?

    我曾经使用过一个命令行 SMTP 邮件程序 作为试用版的限制 它允许您在每个 Windows 会话中最多接收 10 封电子邮件 如果您重新启动计算机 您可能还会收到 10 个以上 我认为这种共享软件破坏非常巧妙 我想在我的应用程序中复制它
  • Visual Studio 在构建后显示假错误

    我使用的是 Visual Studio 2017 构建后 sln在调试模式下 我收到错误 但是 当我通过双击错误列表选项卡中的错误来访问错误时 错误会从页面中消失 并且错误数量也会减少 我不太确定这种行为以及为什么会发生这种情况 有超过 2
  • Python 属性和 Swig

    我正在尝试使用 swig 为一些 C 代码创建 python 绑定 我似乎遇到了一个问题 试图从我拥有的一些访问器函数创建 python 属性 方法如下 class Player public void entity Entity enti
  • 将 Long 转换为 DateTime 从 C# 日期到 Java 日期

    我一直尝试用Java读取二进制文件 而二进制文件是用C 编写的 其中一些数据包含日期时间数据 当 DateTime 数据写入文件 以二进制形式 时 它使用DateTime ToBinary on C 为了读取 DateTime 数据 它将首
  • 为什么可以通过ref参数修改readonly字段?

    考虑 class Foo private readonly string value public Foo Bar ref value private void Bar ref string value value hello world
  • 使用valgrind进行GDB远程调试

    如果我使用远程调试gdb我连接到gdbserver using target remote host 2345 如果我使用 valgrind 和 gdb 调试内存错误 以中断无效内存访问 我会使用 target remote vgdb 启动
  • 为什么我的单选按钮不起作用?

    我正在 Visual C 2005 中开发 MFC 对话框应用程序 我的单选按钮是 m Small m Medium 和 m Large 它们都没有在我的 m Summary 编辑框中显示应有的内容 可能出什么问题了 这是我的代码 Pizz
  • C++ 中的双精度型数字

    尽管内部表示有 17 位 但 IEE754 64 位 浮点应该正确表示 15 位有效数字 有没有办法强制第 16 位和第 17 位为零 Ref http msdn microsoft com en us library system dou
  • 高效列出目录中的所有子目录

    请参阅迄今为止所采取的建议的编辑 我正在尝试使用 WinAPI 和 C 列出给定目录中的所有目录 文件夹 现在我的算法又慢又低效 使用 FindFirstFileEx 打开我正在搜索的文件夹 然后我查看目录中的每个文件 使用 FindNex
  • 检测到严重错误 c0000374 - C++ dll 将已分配内存的指针返回到 C#

    我有一个 c dll 它为我的主 c 应用程序提供一些功能 在这里 我尝试读取一个文件 将其加载到内存 然后返回一些信息 例如加载数据的指针和内存块的计数到 c Dll 成功将文件读取到内存 但在返回主应用程序时 程序由于堆损坏而崩溃 检测
  • C++ new * char 不为空

    我有一个问题 我在 ASIO 中开发服务器 数据包采用尖头字符 当我创建新字符时 例如char buffer new char 128 我必须手动将其清理为空 By for int i 0 i lt 128 i buffer i 0x00
  • OpenGL:仅获取模板缓冲区而没有深度缓冲区?

    我想获取一个模板缓冲区 但如果可能的话 不要承受附加深度缓冲区的开销 因为我不会使用它 我发现的大多数资源表明 虽然模板缓冲区是可选的 例如 排除它以利于获得更高的深度缓冲区精度 但我还没有看到任何请求并成功获取仅 8 位模板缓冲区的代码
  • 使用 C 在 OS X 中获取其他进程的 argv

    我想获得其他进程的argv 例如ps 我使用的是在 Intel 或 PowerPC 上运行的 Mac OS X 10 4 11 首先 我阅读了 ps 和 man kvm 的代码 然后编写了一些 C 代码 include
  • 如何使用 C++11 using 语法键入定义函数指针?

    我想写这个 typedef void FunctionPtr using using 我该怎么做呢 它具有类似的语法 只不过您从指针中删除了标识符 using FunctionPtr void 这是一个Example http ideone

随机推荐