首页 > 编程语言 >5.1.1 C++函数模板和类模板注意事项

5.1.1 C++函数模板和类模板注意事项

时间:2024-12-09 10:58:16浏览次数:7  
标签:5.1 函数 age C++ person void 模板 name

一)函数注意事项
·1.自动类型推导,必须推导出一致的数据类型T,才可以用。
·2.模板必须要确定出T的数据类型,才可以使用。(必须给出类型表达式)
二)普通函数与函数模板的区别
·1.普通函数调用时可以发生自动类型转换(隐式类型转换)。
·2.1函数模板调用时,如果利用“自动类型推导”,不会发生隐式类型转换。
·2.2函数模板调用时,如果利用“显示指定类型”的方式,可以发生隐式类型转换。
三)函数调用规则如下
·1.如果函数模板和普通函数都可以实现,优先调用普通函数。
·2.可以通过空模板参数列表来强制调用函数模板。
·3.函数模板也可以发生重载。
·4.如果函数模板可以产生更好的匹配,优先调用函数模板。
(例如当普通函数为int类型,当给定参数不是int类型,此时调用函数模板)

#include<iostream>
using namespace std;
#include<string>
void  myprint(int a, int b)//1.普通函数
{
	cout<<"普通函数"<<endl;
}
template<class T> //1.函数模板
void myprint(T a, T b)
{
	cout << "函数模板" << endl;
}
template<class T>
void myprint(T a, T b,T c)
{
	cout << "函数重载的模板" << endl;
}
void test()
{
	int a = 10;
	int b = 20;
	int c = 10;
	myprint(a, b);
	//2.通过空模板调用模板函数
	myprint<>(a, b);
	//3.模板函数重载调用
	myprint(a, b,c);
	//4.如果函数模板产生更好的匹配,优先调用函数模板
	char a1 = 'a';
	char b1 = 'b';
	myprint(a1, b1);
}
int main()
{
	test();
	system("pause");
	return 0;
}

学习模板可以在STL中能够运用系统提供的模板。
四)类模板
1)类模板与函数模板区别主要有两点
·1.类模板没有自动类型推导的使用方式。
·2.类模板在模板参数列表中可以有默认参数。

#include<iostream>
using namespace std;
#include<string>
//template<class typeName,class typeage>//1. 类模板不能用自动推导类型使用
template<class typeName, class typeage=int>//2.模板中有默认参数
class person
{
public:
	person(typeName name,typeage age)
	{
		this->m_age = age;
		this->m_name = name;
	}
	typeName m_name;
	typeage m_age;
};
void test()
{
	//1.类模板不能用自动推导类型使用
	//person p("张三", 20);
	//person<string, int>p1("张三", 19);//只能用显示指定类型
	//cout << p1.m_name << p1.m_age << endl;
	//2.类模板在模板参数列表中可以有默认参数
	person<string>p1("张三", 19);
	cout << p1.m_name << p1.m_age << endl;
}
int main()
{
	test();
	system("pause");
	return 0;
}

2)类模板中成员函数和普通类中成员函数创建时机是有区别的
·1.普通类中的成员函数一开始就可以创建。
·2.类模板中的成员函数在调用时才创建。

#include<iostream>
using namespace std;
#include<string>
class person1//类1
{
public:
	void showperson1()
	{
		cout << "showperson1" << endl;
	}
};
class person2//类2
{
public:
	void showperson2()
	{
		cout << "showperson2" << endl;
	}
};
template<class T>//创建类模板
class myclass
{
public:
	T obj;
	void func1()
	{
		obj.showperson1();
	}
	void func2()
	{
		obj.showperson2();
	}
};
void test()
{
	myclass<person2>m; //调用类模板中函数,类模板中成员函数,并不是一开始就创建的,而是在模板调用时才生成
	//m.func1();//类型为person1时才调用
	m.func2();//类型为person2时才调用
}
int main()
{
	test();
		system("pause");
	return 0;
}

3)当类模板碰到继承时,需要注意以下几点
·1.当子类继承的父类是一个类模板时,子类在声明的时候,要指定出父类中T的类型。
·2.如果不指定,编译器无法给子类分配内存。
·3.如果想灵活指定出父类中T的类型,子类也需变为类模板。
4)类模板成员函数类外实现

#include<iostream>
using namespace std;
#include<string>
template<class T1,class T2>
class person
{
public:
	person(T1 name, T2 age);	
	void print();
	T1 m_name;
	T2 m_age;
};
//构造函数类外实现
template<class T1,class T2>
person<T1,T2>::person(T1 name, T2 age)
{
	this->m_name = name;
	this->m_age = age;
}
//成员函数类外实现
template<class T1, class T2>
void person<T1, T2>::print()
{
	cout << "姓名:" << this->m_name << "年龄:" << this->m_age << endl;
}
void test()
{
	person<string, int> p("y", 19);	
	p.print();
}
int main()
{
	test();
	system("pause");
	return 0;
}

5)模板分文件编写
1,问题:类模板中成员函数创建时机是在调用阶段,导致分文件编写时链接不到。
解决方法有两种
·1.直接包含.cpp源文件。
·2.将声明和实现写到同一个文件中,并更改后缀名为.hpp,hpp是约定的名称,并不是强制。

//#include "person.cpp"//第一种方式,直接包含源文件
//1.hpp文件
#pragma once
#include<iostream>
using namespace std;
template<class T1, class T2>
class person
{
public:
	person(T1 name, T2 age);
	void print();
	T1 m_name;
	T2 m_age;
};
//1.cpp文件
template<class T1, class T2>
person<T1, T2>::person(T1 name, T2 age)
{
	this->m_name = name;
	this->m_age = age;
}
template<class T1, class T2>
void person<T1, T2>::print()
{
	cout << "姓名:" << this->m_name << "年龄:" << this->m_age << endl;
}
//1.调用程序
#include <iostream>
using namespace std;
#include"person.cpp"//类模版成员函数是在调用时才生成。所以调用创建文件。
void test()
{
	person<string,int> p("孙悟空",20);
	p.shoeprint();
}
int main()
{
	test();
	system("pause");
	return 0;
}

//主程序
#include<iostream>
using namespace std;
#include<string>
//第二种解决方式,将.h和.cpp的内容写在一起,改后缀名为.hpp文件。//主流方法
#include "person.hpp"
void  test()
{
	person<string, int>p("张三", 19);
	p.print();
}
int main()
{
	test();
	system("pause");
	return 0;
}

6)类模板与友元
1.全局模板类内实现-直接在类内声明友元即可。
2.全局函数类外实现,需要提前让编译器知道全局函数的存在。

#include <iostream>
#include<string>
using namespace std;
//2.全局函数类外实现,提前让编译器知道person类存在
template<class T1, class T2>//提前声明person类
class person;
template<class T1, class T2>//将全局函数放到前面
void print1(person<T1, T2>p)
{
	cout << "类外实现姓名:" << p.m_name << "年龄:" << p.m_age << endl;
}
template<class T1,class T2>
class person
{
	//1.通过全局函数在类内实现,打印print信息
	friend void print(person<T1,T2>p)//全局函数声明和实现写在一起了
	{
		cout << "姓名:" <<p.m_name << "年龄:" << p.m_age << endl;
	}
	//2.通过全局函数在类外实现,
	//需要加空模板参数列表
	//如果全局函数是类外实现,需要让编译器提前知道这个函数的存在
	friend void print1<>(person<T1, T2>p);
public:
	person(T1 name,T2 age)
	{
		this->m_name = name;
		this->m_age = age;
	}
private:
	T1 m_name;
	T2 m_age;
};
void test()//测试1
{
	person<string,int> p("张三",19);
	print(p);
}
void test1()//测试2
{
	person<string, int> p("张三", 19);
	print1(p);
}
int main()
{
	test1();
	system("pause");
	return 0;
 }

标签:5.1,函数,age,C++,person,void,模板,name
From: https://blog.csdn.net/wgf350357114/article/details/144180928

相关文章

  • 你有用过哪些模板引擎?你觉得哪个好用?为什么?
    我作为一个大型语言模型,并没有真正“使用”模板引擎的方式如同前端开发者那样。我没有运行JavaScript代码或构建网页的能力。我的工作方式是基于文本的处理和生成。我更像是理解并能生成使用模板引擎的代码,而不是一个实际操作的用户。但是,我可以根据大量的代码示例和开发者讨论......
  • 模板函数使用is_same的注意事项
    在模板函数中使用is_same判断类型的话,编译器会实例化所有路径,即使某些路径在运行时不会被执行。这意味着编译器会检查所有的分支,确保它们都是有效的。例如如果存在从string转为int的路径,即便T为string时不会进入该路径,依旧会编译失败。template<classT>voidf(){ if(is_sa......
  • ZZNUOJ_1077 : 字符串加密(C/C++/Java算法源码&注释)
    题目描述输入一串字符和一个正整数k,将其中的英文字母加密并输出加密后的字符串,非英文字母不变。加密思想:将每个字母c加一个序数k,即用它后面的第k个字母代替,变换公式:c=c+k。如果字母为z,则后一个字母是a,也就是字母字符形成一个圆。输入输入第一行是一个整数k,k是int范围......
  • ZZNUOJ_1274:位数和(C/C++/Java算法源码&注释)
    题目描述位数和即Digit-sum。一个整数的Digit-sum就是:十进制表示下的整数的各个位数的和,例如1234的Digit-sum是1+2+3+4=10,3443的Digit-sum是3+4+4+3=14. 现在问题是:给你三个正整数A,B和C,在A和B之间找一个整数X,使得X的Digit-sum与C的Digit-sum的最接近,如果存在多个X则......
  • 【C++】vector
    `vector`是一种容器,广泛存在于多种编程语言中,如C++、Rust、Java等。它是一种动态数组,可以存储任意类型的元素,并且可以根据需要自动调整大小。下面我将详细介绍`vector`的概念和使用方法,主要以C++中的`std::vector`为例。###1.概念-**动态数组**:与静态数组不同,`ve......
  • 【java】利用aspose.words的ReportingEngine填充word模板
    详情见:https://gitee.com/javadog-net/boot-apose前言⏲️本文阅读时长:约10分钟......
  • 【题解】P5787 二分图 /【模板】线段树分治
    二分图最简单的方法是染色法实现,但是扩展域并查集也可以实现,有两个集合\(S,T\),具体的是相连边的两个点\(x,y\)总是在不同的两个集合中,若出现在同一集合中即不是一个二分图。对于时间段建边考虑用线段树储存,线段树按照时间轴划分,将将对应时间区间的节点储存上当前连边操作,小时......
  • 模板方法模式
    介绍定义:模板方法模式在一个方法中定义一个算法的骨架,将一些步骤延迟到子类中实现。模板方法使得子类可以在不改变算法结构的情况下,重新定义该算法的某些步骤。示例:/***咖啡因饮料冲泡法*/publicabstractclassCaffeineBeverage{/***模板方法,咖啡因饮料有......
  • 二叉树的C++实现
    文章目录一、二叉树存储的物理结构1.1二叉树基础知识1.2二叉树的存储1.2.1单个节点的存储:1.2.2二叉树的存储二、C++代码实现2.1每个二叉树节点结构体:2.2二叉树类的定义2.3方法实现一、二叉树存储的物理结构1.1二叉树基础知识(1)二叉树的定义:每个节点最多......
  • 【C++】堆栈的使用 | 堆栈的大小 | 动静态分配问题
    栈和堆的使用:1.栈区先定义的变量放到栈底,地址高,后定义的变量放到栈顶,地址低,因此是向下生长的,堆区则相反2.栈区主要存在局部变量和函数参数,其空间的管理由编译器自动完成,无需手动控制,堆区是自己申请的空间,在不需要时需要手动释放3.频繁的申请空间和释放空间,容易造成内存......