C++模板详细入门剖析(附源码)

3 篇文章 0 订阅
1 篇文章 0 订阅

作者:周洪璋

C++模板是C++很重要的一个技术分支,可以从字面意思来理解他的作用,就相当于创建一个模板可以适配多种函数或者类等等,大大节省了工作效率。

C++ 提供了两种模板,分别为函数模板和类模板

1. 函数模板:

 template<class T>
int add(T a,T b)//模板函数
{
    cout<<a*b<<endl;
}
int main()
{
    int a;
    int b;
	add(a,b);//函数模板可以自动推导参数的类型
	add<int>(a,b);
}

上面是最简单的函数模板,步骤:
1: template<class t>
2:替换相应的 数据类型
如void c(int a ,int b)->void c(t a, t b),注意要同种类型才可
3:调用 c(a,b)或者是c<>(a,b)或者

c <int>(a,b)

2. 函数模板和普通模板区别:

代码1:

 int add(int a,int b)
{
    cout<<a+b<<endl;
}
template<class T>
int add(T a,T b)//模板函数
{
    cout<<a*b<<endl;
}
void test02()
{
    char a=10,b=30;
    add(a,b);//调用函数模板不是同类型优先考虑模板函数,因为普通函数要自动转换,模板函数不需要
}
void test01()
{
    int a=10;
    char b=20;
    add(a,a);//普通函数
    add<>(a,a);//函数模板
    add<int>(a,a);//函数模板
    add(a,b);//普通函数,自动类型转换
   // add<>(a,b);//error模板函数不能够自动类型转换
}
int main()
{
	test02();
	test01();
}

总结:

  1. 函数模板不允许自动类型转化 普通函数能够自动进行类型转化
  2. 有两个不同参数时,优先调用普通函数,因为普通函数可以隐式类型转换。
  3. 函数模板不允许自动类型转换,必须严格匹配类型。
  4. 如果传入的实参没有和普通函数的形参一样,就会优先调用函数模板,因为普通函数要自动类型转换

模板实现的原理

  • c/c++编译过程都需要经过4步编译,分别是预编译,编译,汇编,链接
    分别对应 gcc -E ,gcc -s gcc -c gcc ;
    hello.i hello.s hello.o hello.exe*/

  • 本质是函数重载,进行二次编译,第一次先把所有的T替换实参的类型,

  • 第二次在进行实际的运算,第二次就是一个普通函数。

类模板

类模板和函数模板相似,主要解决多个类功能相同但是数据类型不同的问题。

template<class T1,class T2>
class annimal
{
    T1 a;
    T2 b;
public:
    annimal(T1 a,T2 b)
    {
        this->a=a;
        this->b=b;
        cout<<this->a<<this->b<<"类模板"<<endl;
    }

};
void test03()
{
    annimal<string,int>("王者荣耀",20);//显示指定

总结:

  1. 定义方法为:
template<class T1,class T2>

可以定义多个 class 名字自己取
2.替换掉相应的数据类型。
3.在调用该类的对象函数或者是对象成员时必须要显示该类型如:

annimal<string,int>("王者荣耀",20);
要指定王者荣耀以及20的类型,这里指定为
string和int 其实就是指定T1,和T2的数据类型

类模板派生普通类

类模板在作为基类被继承的时候,子类必须要确定基类的大小

template<class T1>
class base()
{
	public:
	base(T1 a)
	{
		a=10;
	}
}
//子类继承
class son:base<int>//指定为int型
{
	son():base<int>(20)//调用父类指定的构造函数,否则将会默认调用父类无参构造
	{}
}

类模板类外实现

类模板的类内实现就是在类里面调用模板,上面实现的方式时类内实现,这里不在啰嗦,主要讲类外实现。

template<class T1,class T2>
class annimal
{
    T1 a;
    T2 b;
public:
    annimal(T1 a,T2 b);
};
template<class T1,class T2>//重新定义
annimal<T1,T2>::annimal(T1 a,T2 b)//引用,否则将会成为全局函数
{
    cout<<a<<" ----"<<b<<endl;
}
void test04()
{
    annimal<float ,int>p(10,20);
}

总结:

1.现在内部声明,在外部定义

 annimal<T1,T2>::annimal(T1 a,T2 b)//引用,否则将会成为全局函数

2.外部定义时要重新引用该模板

template<class T1,class T2>//重新定义

3。调用该函数和平常的模板类一样

annimal<int int> p(10,10);

我们类模板的成员函数是在调用是在调用时,没用调用编译器是不会创建这个函数,只有声明。

类模板的分文件问题

当在头文件定义一个类模板,类模板的成员函数在其他文件实现时,调用该类的类模板成员函数将会报错,提示你找不到相关定义,因为在调用该成员函数时会在头文件寻找,如果在该头文件找不到实现的方法,讲会报错,这就是一个分文件存在的问题。
:解决方法是写在同一个文件里面,通常都用后缀名.hpp来命名,告诉调用者这是一个类模板。

template<class T1,class T2>
class annimal
{
    T1 a;
    T2 b;
public:
    annimal(T1 a,T2 b);
};

类模板碰到友元函数

友元函数可以直接在类模板里面定义,此时该友元函数是一个全局变量,虽然他在类模板里面定义
方法一:直接在类模板里面声明

template<class T1,class T2>
class my
{

    T1 a;
    T2 b;
public:
friend void other1( my<T1,T2> &p)
{
   p.a=10;
   cout<<p.a<<endl;
}
    int ai;
};

方法二,在内部声明友元函数,在外部定义

template<class T1,class T2> 
class my;//进行声明,不然执行到友元函数时会找不到my这个类
template<class T1,class T2>//这个友元函数时一个函数模板,所以在此定义,此时定义不一定要和雷类模板得名字相同
void other( my<T1 ,T2> &p)
{
   cout<<"友元函数"<<endl;
}
template<class T1,class T2>
class my
{
    T1 a;
    T2 b;
public:
friend void other<>( my<T1 ,T2> &p);
};
  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

魔动山霸

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值