首页 > 编程语言 >【C++面向对象】泛型编程(模板) 新手小白都能懂!

【C++面向对象】泛型编程(模板) 新手小白都能懂!

时间:2024-08-12 20:58:56浏览次数:12  
标签:oper 函数 C++ 面向对象 参数 template 泛型 模板

目录

泛型编程是什么?

顾名思义,“泛型”即“广泛的类型”,即不拘泥于一种特定类型的编程方法。在泛型编程时,我们通常使用一个或多个类型占位符来表示一种或多种类型,这些类型对于模板而言就像是函数的参数一样,调用时都是不可或缺的(新版本的C++标准中加入了函数模板隐式实例化的定义,系统会根据函数参数推导模板类型参数)。

为什么要使用泛型编程呢?原因很简单,在面对不同的参数类型要实现相同的功能时,频繁进行函数重载会显得非常低效。此时不妨使用泛型编程,它会使得代码可读性和效率大幅提升。

模板和泛型编程的关系?

模板是泛型编程实现的重要手段。声明一个类/函数是类模板/函数模板,需要使用template关键字。下文主要介绍模板的基本方法和技巧,进阶的技巧可以期待 我以后的文章。

模板分为函数模板类模板。下文将逐一介绍它们的使用方法。

函数模板

定义

声明一个函数是函数模板的框架如下:

template <typename T>
func_type func_name(parameter list)
{
	function body;
}

其中,template是关键字;typename是模板类型参数的占位符(也可用class代替);T是我们自主定义的类型名占位符,可以用任何符合规定的标识符替代;func_type是函数返回类型;func_name是函数名;parameter list是函数参数列表(参数不一定都必须是定义的类型占位符类型,但一般情况下都会保留至少一个不是基本类型的参数虽然一个不留也不会错,但这样你还用模板干嘛 );function body是函数内容。

为了更好地理解函数模板,以下是一个函数模板的实例:

template <typename T>
bool compare(T a, T b)
{
	return a > b;
}
调用

以下是一个调用函数模板的实例:

#include <iostream>
using namespace std;

template <typename T>
bool compare(T a, T b)
{
	return a > b;
}

int main()
{
	cout << "5" << (compare <int>(5, 6) ? ">" : "<=") << "6" << endl;
	cout << "0.75" << (compare <double>(0.75, 0.333) ? ">" : "<=") << "0.333" << endl;
	cout << "a" << (compare('a', 'A') ? ">" : "<=") << "A" << endl;
	return 0;
}

运行上面的代码,将会输出以下结果:

5<=6
0.75>0.333
a>A

观察上面的代码,第一、二个输出展现的是显式实例化,即在调用函数时直接指定模板中T的具体指代。而第三个输出展现的是隐式实例化,即在调用函数时不直接指定T,而是让系统在编译时根据参数的类型推导出模板类型参数。

顺便扯一嘴,虽然看起来它们都是调用了同一个函数,但其实通过汇编代码就能发现,编译器产生了不同的函数,感兴趣的读者可以自己研究一下。

请注意:隐式实例化是现代C++标准的内容,部分年代久远的编译器可能不支持,请慎用。另关于实例化的内容会在以后的文章中讲解。

类模板

定义

类模板的声明与函数模板相似,请直接看下面一个实例:

template <typename T>
class oper
{
private:
	T a, b;

public:
	oper() {};
	oper(T ia, T ib)
	{
		this->a = ia;
		this->b = ib;
	}
	~oper() {};

public:
	bool compare()
	{
		return a > b;
	}

	T add()
	{
		return a + b;
	}
};

这是类模板的成员函数在类内定义的情况。如果在类外定义,也需要前置一个模板声明。例如下面的实例和上面的代码是等价的:

template <typename T>
class oper
{
private:
	T a, b;

public:
	oper() {};
	oper(T, T);
	~oper() {};

public:
	bool compare()
	{
		return a > b;
	}

	T add();
};

template <typename T>
oper <T>::oper(T ia, T ib)
{
	this->a = ia;
	this->b = ib;
}

template <typename T>
T oper <T>::add()
{
	return this->a + this->b;
}

可以看到与一般的在类外定义成员函数的方法不同,这时空间解析运算符::前面的类名加了个<T>,这是模板参数,一定不能丢!!!

调用

类模板没有隐式实例化的概念,因此定义一个类模板对象时必须指定模板参数。

#include <iostream>
using namespace std;

template <typename T>
class oper
{
private:
	T a, b;

public:
	oper() {};
	oper(T ia, T ib)
	{
		this->a = ia;
		this->b = ib;
	}
	~oper() {};

public:
	bool compare()
	{
		return a > b;
	}

	T add()
	{
		return a + b;
	}
};

int main()
{
	oper <int> a(1, 5);
	cout << a.add() << ' ' << (a.compare() ? "1>5" : "1<=5") << endl;
	oper <double> b(0.75, 0.333);
	cout << b.add() << ' ' << (b.compare() ? "0.75>0.333" : "0.75<=0.333") << endl;
	//oper c('a', 'A'); error,报错:缺少类模板"oper"的参数列表
	return 0;
}

运行上面的程序,将会输出以下结果:

6 1<=5
1.083 0.75>0.333

总结/小注

模板参数列表也可以有多个,与函数参数类似地,每个参数之间用,隔开;

模板参数列表也可以有缺省参数,缺省参数规则与函数缺省参数类似,即所有的缺省参数必须放在其它参数之后

点个赞/评论支持一下吧,到现在都没人评论我。。。

标签:oper,函数,C++,面向对象,参数,template,泛型,模板
From: https://blog.csdn.net/LiuJack_2011/article/details/141140742

相关文章

  • c++两人组合账号
    周小灵彤:周小灵彤(六年级)-CSDN博客王小灵弘:wanghongyv-CSDN博客这是联合账号,因为我们俩懒太勤快了(嘻嘻)                                                     ......
  • NDT算法详解与C++实现
    点云匹配在感知环节是一个很重要的信息获取手段,而其中的算法也有几个比较经典了,例如ICP(IterativeClosestPoint,迭代最近点)算法,而本文决定记录学习的是NDT算法,也就是NormalDistributionTransform,正态分布变换算法。什么是正态分布变换算法呢,简言之,就是把空间中的点云进行整......
  • C++基础知识:友元是什么,友元(全局函数做友元)
    在程序里,有些私有属性也想让类外特殊的一些函数或者类进行访问,就需要用到友元的技术友元的目的就是让一个函数或者类访问另一个类中私有成员通俗一点说就是友元,就好比你的闺蜜,你可以让他了解你身上的特有的东西友元的关键字为friend全局函数做友元代码测试:#include......
  • 保姆级下载C++17
    一、下载MSYS2MSYS2是一款跨平台编译套件,方便的帮助我们安装环境,下面是MSYS的官网:MSYS2https://www.msys2.org/下载完成后安装,安装的路径千万不要有中文,把你安装的路径复制一下,以便后续步骤。二、安装GCC安装完成后打开刚才复制的路径,点开msys2.exe,输入以下命令来安装GCCp......
  • windows C++-C++/WinRT 中创建组件和事件(下)
    跨ABI的简单信号如果无需连同事件传递任何形参或实参,则可以定义自己的简单Windows运行时委托类型。以下示例展示Thermometer运行时类的更简易版本。它声明名为SignalDelegate的委托类型,然后使用该类型来引发信号类型事件,而不是具有参数的事件。//ThermometerWRC.i......
  • windows C++-使用 C++/WinRT 的集合
    在内部,Windows运行时集合具有大量复杂的移动部件。但要将集合对象传递到Windows运行时函数,或要实现自己的集合属性和集合类型时,C++/WinRT中有函数和基类可以提供支持。这些功能消除复杂性,并节省大量时间和精力上的开销。IVector是由元素的任意随机访问集合实现的Windo......
  • 2024华为OD笔试机试 - 模拟目录管理功能 (python/c++/java D卷C卷真题算法)
    华为OD机试(C卷+D卷)2024真题目录(Java&c++&python)题目描述实现一个模拟目录管理功能的软件,输入一个命令序列,输出最后一条命令运行结果。支持命令:创建目录命令:mkdir目录名称,如mkdirabc为在当前目录创建abc目录,如果已存在同名目录则不执行任何操作。此命令无输出......
  • C++类和对象(中):构造函数、析构函数、拷贝构造、赋值运算符重载
    文章目录C++类和对象4、类的默认成员函数5、构造函数5.1构造函数的特点5.2实例分析6、析构函数6.1析构函数的特点6.2实例分析7、拷贝构造函数7.1拷贝构造函数的特点7.2实例分析7.3浅拷贝和深拷贝8、赋值运算符重载8.1运算符重载8.1.1运算符重载的特点8.1.2实例分析8.......
  • BOOST c++库学习 之 boost.thread入门实战指南 使用boost.thread库以及读写锁mutex的
    Boost.Thread库简介1.概述Boost.Thread库是Boost库中专门用于处理多线程编程的模块。它提供了一组跨平台的线程管理和同步工具,帮助开发者在C++中更轻松地编写多线程程序。Boost.Thread的设计目标是使多线程编程更加简单、可靠,同时保持高效和可移植性。2.Boost.Thread......
  • C/C++ 知识点:using 关键字
    文章目录一、using关键字1、命名空间别名和成员访问2、类型别名3、继承中的`using`声明4、模板别名5、模板中的`using`声明6、总结前言:C++中的using关键字是一个功能丰富的工具,它主要用于命名空间、类型别名、继承以及模板编程中。下面将详细介绍using关键字的几......