C++函数模板和类模板

这篇具有很好参考价值的文章主要介绍了C++函数模板和类模板。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

C++另一种编程思想称为泛型编程,主要利用的技术是模板
C++提供两种模板机制:函数模板和类模板

C++提供了模板(template)编程的概念。所谓模板,实际上是建立一个通用函数或类,
其类内部的类型和函数的形参类型不具体指定, 用一个虚拟的类型来代表。
这种通用的方式称为模板。模板是泛型编程的基础,泛型编程即以一种独立于任何特定类型的方式编写代码。

即:我们提供一个抽象的函数或类,并不具体指定其中数据的类型,而是某个虚拟类型代替。只提供基本的功能。其具体的数据类型,只在其被调用时视具体情况实例化。

函数模板

举个例子

#include <iostream>
#include <stdio.h>

using namespace std;

template <typename T1,typename T2>             //模板函数声明与定义
T2 test(T1 tmp, T2 tmp1) {

	T2 tmp2 = tmp + tmp1;

	return tmp2;
}

int main(void) {

	cout << "test(10, 5)=" << test(10, 5) << endl;     //调用模板函数,模板函数通过传入的参数自动推导未实例化的类型
	cout << "test(5,'A')=" << test(5,'A') << endl;
	cout << "test(10.5, 5.5) =" << test(10.5, 5.5) << endl;

	system("pause");

	return 0;
}

C++函数模板和类模板,C++,c++,算法,开发语言
函数模板的声明通过关键字template与typename 实现。其中,template告知编译器这是函数模板的声明,typename用来声明虚拟类型。比如你要声明一个模板函数,里面需要两个不同的变量,那么你就需要通过typename声明两个不同的虚拟类型T1,T2。

声明好后,你就可以在函数定义中使用虚拟类型来定义变量,但是要注意,用同一个虚拟类型定义的变量就只能是同种类型,比如用T1定义的变量只能是同种变量,可以是int,也可以是char。这取决于其实例化时被实例化为哪种类型。

C++函数模板注意事项
注意事项:
1、自动类型推导,必须推导出一致的数据类型T,才可以使用
2、模板必须要确定出T的数据类型,才可以使用

using namespace std;
template<class T>
void mySwap(T& a, T& b)
{
	T temp = a;
	a = b;
	b = temp;
}

void test01()
{
	int a = 10;
	int b = 20;
	char c = 'c';
	//1、自动类型推导,必须推导出一致的数据类型T,才可以使用
	mySwap(a, b);
	//mySwap(a, c);推导不出一致的T类型
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
}

template<class T>
void func()
{
	cout << "func()的调用" << endl;
}

void test02()
{
	//2、模板必须要确定出T的数据类型,才可以使用
	func<int>();
}

int main() {
	test01();
	test02();
	return 0;
}

模板函数的调用
1)显式类型调用
可以显式的调用模板函数,即在调用时人为地指明虚拟类型的具体类型。

#include <iostream>
#include <stdio.h>

using namespace std;

template <typename T1,typename T2>             //模板函数声明与定义
T2 test(T1 tmp, T2 tmp1) {

	T2 tmp2 = tmp + tmp1;

	return tmp2;
}

int main(void) {

	cout << "test(5,'A')=" << test<int,char>(5, 'A') << endl;          //<int,char>显式的指明模板的类型

	system("pause");

	return 0;
}

2)自动推导
即不指明具体的数据类型,而让编译器根据传入的数据自动推导出数据类型。

#include <iostream>
#include <stdio.h>

using namespace std;

template <typename T1,typename T2>             //模板函数声明与定义
T2 test(T1 tmp, T2 tmp1) {

	T2 tmp2 = tmp + tmp1;

	return tmp2;
}

int main(void) {

	cout << "test(5,'A')=" << test(5, 'A') << endl;          //自动推导数据类型

	system("pause");

	return 0;
}

模板函数与函数重载

熟悉函数重载的人应该会好奇,如果既有模板函数又有同名的普通函数,而且参数列表的参数个数是一样的,那么在主函数中调用同名函数,编译器具体会调用哪一个呢?

下面看一个例子:

#include <iostream>
#include <stdio.h>

using namespace std;

template <typename T1,typename T2>             //模板函数声明与定义
T1 test(T1 tmp, T2 tmp1) {

	cout << "调用模板函数!" << endl;

	return (tmp + tmp1);
}

int test(int tmp, int tmp1) {                  //重载的普通函数

	cout << "调用普通函数!" << endl;

	return 0;
}

int main(void) {

	char tmp = 'c';
	int tmp1 = 0;
	int a = 5;

	cout << "test(5,'c')=" << test(a, tmp) << endl;     
	cout << "test(5,0)=" << test(a, tmp1) << endl;

	system("pause");

	return 0;
}

C++函数模板和类模板,C++,c++,算法,开发语言
普通函数的两个参数都是int型,在第一次调用test时第二个参数使用的是char型,调用的是模板函数,第二次使用的是int型,调用的是普通函数。

这是为什么呢?理论上来说,模板函数两个都能匹配,使用。而普通函数也能匹配这两次调用的参数(在C语言中,char型变量是可以作为int型参数使用的)。

这是因为模板函数可以自动推导类型,在第一次调用中,两个类型分别被推导为int型与char型。而普通函数是两个int型,虽然也能使用传入的参数,但模板函数明显能更好的匹配参数列表。

也就是说,如果模板函数实例化后的类型能更好的匹配参数列表的话就使用模板函数。

那么当这两个函数都能完全匹配参数列表的时候呢?通过第二次test的调用结果不难发现,这时候,编译器会调用普通函数。

如果一定要使用模板函数,可以使用<>显式的指定使用模板函数。看下面的例子。

#include <iostream>
#include <stdio.h>

using namespace std;

template <typename T1,typename T2>             //模板函数声明与定义
T1 test(T1 tmp, T2 tmp1) {

	cout << "调用模板函数!" << endl;

	return (tmp + tmp1);
}

int test(int tmp, int tmp1) {                  //重载的普通函数

	cout << "调用普通函数!" << endl;

	return 0;
}

int main(void) {

	char tmp = 'c';
	int tmp1 = 0;
	int a = 5;

	cout << "test(5,'A')=" << test(a, tmp) << endl;     
	cout << "test<>(5,0)=" << test<>(a, tmp1) << endl;       //使用<>显式的调用模板函数

	system("pause");

	return 0;
}

C++函数模板和类模板,C++,c++,算法,开发语言

类模板

类模板是为了减少重复工作量而出现的一种进制,当一个类的功能类似只是类型不同时,一个通用的类模板可以根据使用者的需要而生成具体类型的类,从而减少功能重复的代码。

类模板作用:建立一个通用类,类中的成员 数据类型可以不具体制定,用一个虚拟的类型来代表
解释:
template–声明创建模板
typename–表明其后面的符号是一种数据类型,可以用class代替
T–通用的数据类型,名称可以替换,通常为大写字母

在类内部定义与声明

#include <iostream>
#include <stdio.h>

using namespace std;

template <typename T>
class DEMO {

public:
	DEMO(T data) {
		this->data = data;
	}

	~DEMO() {

	}

	int GetData() {
		return this->data;
	}

private:
	T data;
};


template <typename T,typename T1>
class DEMO1 {

public:
	DEMO1() {

	}

	~DEMO1();

private:
	T data;
	T1 ch;
};


int main(void) {

	DEMO<int> demo(5);           //显示的指定类型为int
	DEMO1<int, char> demo1();    //显示的指定类型分别为int,char
	cout << "data=" << demo.GetData() << endl;
	
	system("pause");

	return 0;
}

类模板的定义与使用使用的是和模板函数一样的关键字。即先声明template,在使用typename声明虚拟类型。

与模板函数不同的是,类模板不能被自动推导出类型,只能显示的指定具体的类型。如上面代码中的 DEMO< int > demo(5),该模板类被显示的指定为int型。

在类外部定义成员函数

在类内部声明成员函数,在类外部定义成员函数时,只要成员函数参数列表中出现了类限定域说明,模板类作为返回类型,模板类作为参数类型,那么就要在成员函数之前声明 template <类型形式参数表>,并且在模板类后加上虚拟参数列表。

#include <iostream>
#include <stdio.h>

using namespace std;

template <typename T>
class DEMO {

public:
	DEMO(T data);
	~DEMO();
	DEMO operator+(int sum);
	int PrintData(DEMO& demo);

private:
	T data;
};


template<typename T>          //出现了类限定域说明
DEMO<T>::DEMO(T data)
{
	this->data = data;
}

template<typename T>         //出现了类限定域说明
DEMO<T>::~DEMO()
{
}

template<typename T>                //出现了作为返回值类型的模板类类型
DEMO<T> DEMO<T>::operator+(int sum)
{
	return *this;
}

template<typename T>               //出现了作为参数类型的模板类类型
int DEMO<T>::PrintData(DEMO<T>& demo)
{
	cout << "data=" << demo.data << endl;
	return 0;
}


int main(void) {

	DEMO<int> demo(5), demo1(15);
	demo.PrintData(demo1);
	demo + 5;

	system("pause");

	return 0;
}

C++函数模板和类模板,C++,c++,算法,开发语言
DEMO< T >中的< T >是虚拟参数列表。

总结来说,只要看到了模板类的类名关键字出现在成员函数参数列表中,就要在成员函数之前声明 template <类型形式参数表>,并且在模板类类名后加上虚拟参数列表。

模板类的继承

分为三种情况。一:子类是模板类,父类是普通类;二:父类是模板类,子类是普通类;三:父类与子类都是模板类。其中第一种情况与两个普通类的继承是一样的。就不说了。

1)父类是模板类,子类是普通类:

#include <iostream>
#include <stdio.h>

using namespace std;

template <typename T>
class FATHER {

public:
	FATHER(T data) {
		this->data = data;
	}

	~FATHER() {

	}

private:
	T data;
};


class SON:public FATHER<int> {        //显示的指明父类的具体类型

public:
	SON(int data):FATHER<int>(data) {
		this->data = data;
	}

	~SON() {

	}

	int GetData() {
		return data;
	}

private:
	int data;
};

int main(void) {

	SON son(15);
	cout << "data=" << son.GetData() << endl;

	system("pause");

	return 0;
}

子类是一般类,父类是模板类,继承时必须在子类里实例化父类的类型参数。其实这很好理解,因为在子类对象构造之前,会先调用父类的构造函数,父类为模板类,要想实例化,需要有指定的类型。

2)父类与子类都是模板类:

#include <iostream>
#include <stdio.h>

using namespace std;

template <typename T>
class FATHER {

public:
	FATHER(T data) {
		this->data = data;
	}

	~FATHER() {

	}

private:
	T data;
};


template <typename T1>
class SON:public FATHER<T1> {       //使用子类的模板类型传递到父类中,也可以使用具体的类型

public:
	SON(int data):FATHER<int>(data) {
		this->data = data;
	}

	~SON() {

	}

	int GetData() {
		return data;
	}

private:
	T1 data;
};

int main(void) {

	SON<int> son(15);
	cout << "data=" << son.GetData() << endl;

	system("pause");

	return 0;
}

当子类与父类都是模板类时,继承时也必须在子类里实例化父类的类型参数,值得注意的是,此时实例化的类型参数可以使用子类的模板类型。即让父类与子类在实例化后拥有一样的具体类型。当然也可以使用其它的具体类型。文章来源地址https://www.toymoban.com/news/detail-659458.html

到了这里,关于C++函数模板和类模板的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 浅述C++模板——函数模板及类模板

    模板作为 C++ 的一大特色,对于泛型编程有着重要的作用。同时,对于大规模类似的函数或是类型不确定的类,模板都起了至关重要的作用。 在开始学习模板之前,我们首先需要了解模板。先看下面一个例子: 我们可以轻易发现,对于函数 func_one、func_two,两者实现的功能基

    2024年02月09日
    浏览(46)
  • 【C++】——模板(泛型编程+函数模板+类模板)

    之前我们学习了函数重载,让我们在写相似函数的时候非常方便,但函数重载还有很多不足的地方,比如,每次写相似函数的时候,都要我们重新重载一个逻辑、代码几乎一样的函数,这就导致了我们的效率变低,所以我们今天来学习C++模板的相关知识点,学习完模板之后,

    2024年02月05日
    浏览(48)
  • C++ 函数模板与类模板

    现在的C++编译器实现了C++新增的一项特性–函数模板。函数模板是通用的函数描述,也就是说它们使用泛型来定义函数,其中的泛型可以是具体的类型(如int或double)。通过将类型作为参数传递给模板,可使编译器生成该类型的函数。用于模板允许以泛型的方式编写程序,因

    2023年04月19日
    浏览(48)
  • 【C++】什么是函数模板/类模板?

    函数模板简单来说就是一个模板,与函数参数的类型无关,是一个模子,不是真正的函数,实例化的函数会根据实参的类型 自动 推导类型。 函数模板是一个模板,并不是真正的函数,它是根据传递过来的实参的类型实例化一个具体的函数,相当于我们将重复的事情交给了编

    2024年02月07日
    浏览(60)
  • C++——函数模板与类模板

    C++知识合集 目录 1.泛型编程 2.函数模板 2.1函数模板实例化 2.2函数模板参数的匹配原则 3.类模板 4.模板的分离编译 实际上泛型编程的难度是比较高的,但我们泛型编程的初学者,当然要从简单的地方开始入手。 我们可以写出很多份交换函数,这些函数之间构成函数重载,这

    2024年02月08日
    浏览(44)
  • 【C++】泛型编程 ① ( 函数模板 | 函数模板概念 | 函数模板意义 | 函数模板定义语法 | 函数模板调用语法 | 显式类型调用 | 自动类型推导 )

    在 C++ 语言中 , 泛型编程 的 核心就是 函数模板 和 类模板 ; 函数模板 Function Template 是 C++ 语言 中的 重要特性 ; 函数模板概念 : 建立一个 \\\" 通用函数 \\\" , 不指定该函数的 函数返回值类型 和 函数参数类型 , 仅使用 \\\" 虚拟类型 \\\" 代表 上述 两种类型 , 该 \\\" 通用函数 \\\" 就是 \\\" 函数模

    2024年02月19日
    浏览(39)
  • 【C++从入门到放弃】模板介绍(函数模板、类模板)

    🧑‍💻作者: @情话0.0 📝专栏:《C++从入门到放弃》 👦个人简介:一名双非编程菜鸟,在这里分享自己的编程学习笔记,欢迎大家的指正与点赞,谢谢!   以我们之前所学的知识,假如要实现一个通用的加法函数,那么可以通过函数重载的方式来实现。 使用函数重载虽

    2023年04月14日
    浏览(46)
  • 【C++初阶】八、初识模板(泛型编程、函数模板、类模板)

    ========================================================================= 相关代码gitee自取 : C语言学习日记: 加油努力 (gitee.com)  ========================================================================= 接上期 : 【C++初阶】七、内存管理 (C/C++内存分布、C++内存管理方式、operator new / delete 函数、定位new表

    2024年02月04日
    浏览(46)
  • learn C++ NO.8——初识模板(函数模板、类模板)

    现在是北京时间2023年6月5号13.31分,距离上一篇博客发布已过一周。期间还零零散散进行了一些期末考试,这也说明了我的大一时光快要结束了。我也想抓着期末的尾巴,好好的复习一下前面的所学内容,争取这周能够更一下简单数据结构的博客。 泛型编程是一种编程范式,

    2024年02月07日
    浏览(50)
  • c++模板编程2-函数模板的定义和使用

    两阶段编译检查 在实例化模板的时候,如果模板的参数类型不支持模板中用到的操作符,将会遇到编译期错误,例: 以上例子 add(a, b) 会在编译器报错,但在模板定义的地方并没有出现错误提示,这是因为模板是分两步编译的: 在模板定义阶段,模板的检查并不包含类型参

    2024年02月06日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包