派生类的复制构造函数 如果派生类定义了自己的复制构造函数,该复制构造函数一般应显式使用基类复制构造函数初始化对象的基类部分:
class Base { /* ... */ };
class Derived: public Base
{
public:
Derived(const Derived& d):Base(d) { /*... */ }
};
派生类析构函数 派生类析构函数不负责撤销基类对象的成员。每个析构函数只负责清除自己的成员。
class Derived: public Base
{
public:
~Derived() { /* do what it takes to clean up derived members
*/ }
};
定义函数模板
函数模板是一个独立于类型的函数,可作为一种方式,产生函数的特定类型版本。下面是 compare 的模板版本:
// implement strcmp-like generic compare function
// returns 0 if the values are equal, 1 if v1 is larger, -1 if v1 is smaller
template <typenameT>
int compare(const T &v1, const T &v2)
{
if (v1 < v2) return -1;
if (v2 < v1) return 1;
return 0;
}
模板定义以关键字 template 开始,后接模板形参表,模板形参表是用尖括号括住的一个或多个模板形参的列表,形参之间以逗号分隔。模板形参表不能为空。
inline 函数模板
函数模板可以用与非模板函数一样的方式声明为 inline。说明符放在模板形参表之后、返回类型之前,不能放在关键字 template 之前。
template <typename T> inline T min(const T&, const T&);// ok: inline specifier follows template parameter list
inline template <typename T> T min(const T&, const T&);// error: incorrect placement of inline specifier
类模版
类模版是一个类定义,用来定义一组特定类型的类,类模板用template关键字后接用尖括号<>括住,以逗号分隔的一个或多个模板形参的列表来定义。
template <class Type> class Queue {
public:
Queue (); // default constructor
Type &front (); // return element from head of Queue
const Type &front () const;
void push (const Type &); // add element to back of Queue
void pop(); // remove element from head of Queue
bool empty() const; // true if no elements in the Queue
private:
// ...
};
与调用函数模板形成对比,使用类模板时,必须为模板形参显式指定实参:
Queue<int> qi; // Queue that holds ints
Queue< vector<double> > qc; // Queue that holds vectors of doubles
Queue<string> qs; // Queue that holds strings
模板类型形参
类型形参由关键字 class 或 typename 后接说明符构成。在模板形参表中,这两个关键字具有相同的含义,都指出后面所接的名字表示一个类型。
它可以用于指定返回类型或函数形参类型,以及在函数体中用于变量声明或强制类型转换。
typename 与 class 的区别
在函数模板形参表中,关键字 typename 和 class 具有相同含义,可以互换使用,两个关键字都可以在同一模板形参表中使用。 关键字 typename 是作为标准 C++ 的组成部分加入到 C++ 中的,因此旧的程序更有可能只用关键字 class。
在模板定义内部指定类型
通过在成员名前加上关键字 typename 作为前缀,可以告诉编译器将成员当作类型。
template <class Parm, class U>
Parm fcn(Parm* array, U value)
{
typename Parm::size_type * p; // ok: declares p to be a pointer
}
非类型模板形参
模板形参不必都是类型。
template <class T, size_t N>
void array_init(T (&parm)[N])
{
for (size_t i = 0; i != N; ++i) {
parm[i] = 0;
}
}
通常,当使用类模板的名字的时候,必须指定模板形参。这一规则有个例外:在类本身的作用域内部,可以使用类模板的非限定名。例如,在默认构造函数和复制构造函数的声明中,名字 Queue 是 Queue<Type> 缩写表示。
编译器不会为类中使用的其他模板的模板形参进行这样的推断,因此,在声明伙伴类 QueueItem 的指针时,必须指定类型形参: QueueItem<Type> *head; // pointer to first element in Queue
在类外部定义成员模板
当成员模板是类模板的成员时,它的定义必须包含类模板形参以及自己的模板形参。首先是类模板形参表,后面接着成员自己的模板形参表。 template <class T> template <class Iter> //第一个模板形参表 template<class T> 是类模板的,第二个模板形参表 template<class Iter> 是成员模板的。
void Queue<T>::assign(Iter beg, Iter end)
{
destroy(); // remove existing elements in this Queue
copy_elems(beg, end); // copy elements from the input range
}