《STL源码剖析》学习-- 1.9-- 可能令你困惑的C++语法1

最近在看侯捷的《STL源码剖析》,虽然感觉自己c++看得比较深一点,还是感觉还多东西不是那么明白,这里将一些细小的东西或者概念记录一下。

有些东西是根据《C++编程思想》理解的,记录一下加深印象。

STL没有太多的OO(object oriented),基本思想是GP(Generic Programming)。模板是泛型编程最基础的东西。

这里主要针对1.9节 可能令你困惑的C++语法 所列出来的组态进行讲解,因为书上基本没什么讲解。

1、模板 template

1.1 默认模板参数

很简单的类似于函数的默认参数,只要在后面加等于具体的类名即可以了。

如:template<class T, class U = char> void f() { T a; U b; };

1.2 typename

 如果在用模板定义的函数内如果不用typename标出类名,则只能把标示符当做类的静态成员,可以访问,但却不能新建类型,

如下代码:id为嵌套的类型。此时typename的作用是通知编译器,被限定的标示符为一个类型。

template<typename T>
class M{
	//typename T::id i;
	T::id i;
public:
	void f(){ i.g();}
};

class X{
public:
	class id{
	public:
		void g(){
			cout <<"x" <<endl;
		};
	};
};

当没有typename时,无法定义i,但是我用函数时确实可以的,如下:

template<typename T>
void func(){
	T::id i;
	i.g();
}
int main(){
	func<X>();
	system("pause");

}

可能是不同编译器的原因,为了程序稳定性,模板编程过程中还是最好用typename。

1.3 模板类型推断

在实例化类模板时,总是需要使用尖括号并且提供所有的非默认模板参数;然而在实例化函数模板时,经常可以省略模板参数。

如:

template< typename T> const T& min(const T& a, const T& b){

return (a<b)? a:b;

}

可以通过加尖括号来调用,也可以不,让编译器从函数的参数中推断出模板的类型,这就是类型推断。

如调用min可以如下:

int i,j;

int z= min(i,j);
但此时i,j类型必须完全一致,如果不一致,即使可以进行类型转换(如int 和 float),但是编译器依然会报错,此时必须明确指出模板类型。

1.4 偏特化

一般的往往将偏特化理解为给定模板中的部分模板参数以具体的类,余下的泛化。其实不然,在本书3.4节traits编程技法一节,提到,“所谓partial specialization 的意思是提供另一份template的定义式,而其本身仍为templatized。”,“针对(任何)template参数更进一步的条件限制所设计出来的一个特化版本”。

全特化就是所有的模板都为具体的类。

T* 特化允许用指针类型匹配的模式(也只能匹配指针类型),const T* 特化允许使用指向const的指针 类型匹配(也只能匹配指向const的指针)。

注意,类模板可以偏特化,而函数模板不可以偏特化,即函数名后不可以加<>,但是可以通过重载达到类似偏特化的效果。

当有好多个版本的函数符合模板函数规则时,为了避免二义性,编译器总是选择特化程度最高的的模板。

如 template<class T,class U> void f() { T a; U b; };

某个特化版本为 template<> void f<int,char>() { int a; char b; };

某个偏特化版本为 template<class U> void f<int,U>() { int a; U b; };


1.5模板和友元(主要是限定友元)bound friend templates

class template 的某个具体实现与friend function template的某个具体实现有一对一的关系。

友元函数模板必须提前声明,本书中写到GCC中不需要前置声明。

如下,f()为Friendly类的友元函数,都为模板。此例中两者都是int的示例,注意Friendly中的f的声明里尖括号(或者<T>,不写也很容易推断),诉编译器f是一个模板,而不是普通函数,否则编译器就会找普通函数而找不到。

template<class T> class Friendly;
template<class T> void f(const Friendly<T>&);

template<class T> 
class Friendly{
	T t;
public:
	Friendly(const T& theT):t(theT){}
	friend void f<>(const Friendly<T>&);
	void g(){f(*this);}
};

template<class T>
void f(const Friendly<T>& fo){
	cout << fo.t << endl;
}
void h(){
	f(Friendly<int>(1));
}

int main(){
	h();
	Friendly<int>(2).g();
}


 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值