C++学习 十七、类模板

前言

本篇学习C++中的泛型编程之二,类模板。

类模板

类模板与函数模板类似,用于指导编译器生成类,因此也有模板实例化和具体化。

定义类模板

使用template<typename T>模板头,提示编译器是一个模板。

template<typename T>
class TemplateClass{
    private:
        T a_;
        T b_;
    public:
        TemplateClass(T a, T b);
        T sum();
};

template<typename T>
TemplateClass<T>::TemplateClass(T a, T b){
    a_ = a;
    b_ = b;
}

template<typename T>
T TemplateClass<T>::sum(){
    return a_ + b_;
}

类模板声明需要注意:

  • 成员名不能与模板参数名相同;
  • 模板参数可以有多个,template<typename T1, typename T2>
  • 模板可以拥有非类型参数,template<typename T, int n>,但非类型参数不能是浮点型;
  • 不同类模板或函数模板的模板参数名可以重复使用。

类模板定义需要注意:

  • 在外部定义成员函数时时,需要添加模板头template<typename T>和类限定符TemplateClass<T>::
  • 如果在类内定义成员函数(内联),则可省略模板头和类限定符。

模板具体化

从类模板生成实际类的过程就是具体化,包括实例化,显式具体化和部分具体化。

隐式实例化

使用模板类创建指定模板参数类型的对象,就是隐式实例化。

TemplateClass<int> tc(2, 3);

注意:模板类隐式实例化必须显式指定模板类型,这点与函数模板不同。

显式实例化

使用关键字template指出类模板的参数类型,就是显式实例化。

template class TemplateClass<double>;

显式具体化

如果针对某种类型的类需要不同的实现,比如int类与int*类明显实现方法不一样,则可以通过显式具体化指定特定类型的生成:

template <> class TemplateClass<int*>{
	// ...
};

部分具体化

还可以在多模板类型参数中的指定某个参数的具体类型:

template <typename T1, typename T2> class TTC{ // general
// ...
};
template <typename T1> class<T1, int> TTC{ // partial
// ...
};

模板编译

类模板和函数模板尽量使用包含编译,即把模板声明和定义放在同一个头文件中,需要使用模板的文件包含模板头文件。

分离编译可能导致链接错误。这是由于,分离编译时,编译器单独把每个cpp文件编译成单独的.obj文件,然后链接成.exe文件。

模板在分离编译时,由于在模板.cpp文件中没有被调用,没有生成模板实例,因此在链接时其它文件找不到类和函数实例,即报链接错误。

模板成员

模板也可以作为类成员:

template<typename T> class C{
	public:
		template<typename U>
		U print();
};

模板与友元

非模板友元

非模板友元是一个常规函数:

template<typename T> class D{
	public:
		T a_;
		friend void printd(D<T>&);
};

void printd(D<int>& d){
	std::cout << d.a_;
}

注意:使用非模板友元时,编译器将报一个警告warning: friend declaration declares a non-template function

约束模板友元

友元函数是个函数模板,函数模板参数类型与类模板相同:

template<typename T>
void printd(T &);

template<typename T> 
class D{
	public:
		friend void printd<D<T>>(D<T>&);
};

template<typename T>
void printd(T& d){
// ...
}

约束模板友元:

  • 首先声明友元函数的模板
  • 然后声明类模板
  • 为友元函数模板提供定义

非约束模板友元

函数模板的参数类型与类模板不同:

template<typename T>
class D{
	public:
		template<typename U>
			friend void print(U&);
};

template<typename T>
void print(T&){
// ...
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值