书籍:《C++ 标准程序库》
// http://www.gotw.ca/default.htm
#1. Default Template Parameters (缺省模板参数)
Template classes 可以有缺省参数。例如以下声明,允许你使用一个或两个template参数来声明MyClass对象:
template <class T, class container = vector<T> >//注意,两个“>”之间必须有一个空格,如果你没写空格,“>>”会被解读为移位运算符(shift operator), 导致语法错误. class MyClass;
#2. 关键字 typename
关键字typename被用来作为类型之前的标识符号。考虑下面例子:
template <class T> class MyClass { typename T::SubType * ptr; };
这里,typename指出SubType是class T中定义的一个型别,因此ptr是一个指向T::SubType类型的指针。
如果没有关键字typename,SubType会被当成一个static成员,于是:
T::SubType * prt
会被解释为类型T内的数值SubType与ptr的乘积。
因此,C++的一般规则是, 除了以typename修饰外,template内的任何标识符号都被视为一个值(value)而非一个类型。
#3. Member Template (成员模板)
class member function 可以是个template,但这样的member template既不能是virtual,也不能有缺省参数。例如:
class MyClass { ... template <class T> void f(T); }
Template constructor 是 member template 的一种特俗形式。Template constrcutor 通常用于“在复制对象时实现隐式类型转换”。
注意,template constructor 并不隐藏 implicit copy constructor.如果类型完全吻合,implicit copyconstructor就会被产生出来并调用。
例如:
template <class T>class MyClass { public: // copy ctor with implicit type conversion does not hide implict copy ctor template<class U> MyClass (const MyClass<U>& x); void f(){ MyClass<double> xd; MyClass<double> xd2(xd); // call built-in copy MyClass<int> xi(xd); // calls template ctor } }
#4. 关键字 explicit
通过关键字explicit的作用,我们可以禁止“单参数构造函数(single argument constructor)”被用于自动类型转换。
例如:
class Stack
{
explicit Stack (int size); // create stack with initial size
}
在这里,explicit的应用非常重要。如果没有explicit,这个构造函数有能力将一个int自动转换为Stack。一旦这种情况发生,你甚至可以给Stack指派一个整数值而不会引起任何问题。
Stack s;
s = 40; // Oops,create a new stack for 40elements and assigns it to s
"自动类型转换"动作会把40 转换为有40个元素的stack,并指派给s, 这几乎不是我们所要的结果。如果我们将构造函数声明为explicit,上述赋值操作就会导致编译错误。
注意,explicit同样也能阻绝“以赋值语法进行带有转型操作的初始化”;
Stack s1(40); // OK
Stack s2 = 40; // ERROR