有一个类模板如下,书上例子所示
template <class Type> class Queue {
public:
// empty Queue
Queue(): head(0), tail(0) { }
// copy control to manage pointers to QueueItems in the Queue
Queue(const Queue &Q): head(0), tail(0)
{ copy_elems(Q); }
Queue& operator=(const Queue&);
~Queue() { destroy(); }
// return element from head of Queue
// unchecked operation: front on an empty Queue is undefined
Type& front() { return head->item; }
const Type &front() const { return head->item; }
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
return head == 0;
}
private:
QueueItem<Type> *head; // pointer to first element in Queue
QueueItem<Type> *tail; // pointer to last element in Queue
// utility functions used by copy constructor, assignment, and destructor
void destroy(); // delete all the elements
void copy_elems(const Queue&); // copy elements from parameter
};
|
有一个地方,拷贝构造函数
Queue(const Queue &Q): head(0), tail(0) { copy_elems(Q); }
并没有写上模板参数,因为类模板内部可为默认构造函数和考构进行非限定名推断,但是要定义数据成员,就必须加上模板参数
QueueItem<Type> *head;
类模板的指针定义不会对类进行实例化,只有用到这样的指针时才会对类进行实例化。
类模板的成员函数:
1.必须以关键字
template 开关,后接类的模板形参表。
2.必须指出它是哪个类的成员。
3.类名必须包含其模板形参。
例如一个类外定义的成员函数
: template ret-type Queue::member-name(){...}
类模板成员函数的实例化:
与普通函数模板不同的是,在实例化类模板成员函数的进修,编译器不执行模板实参推断,相反,类模板成员
函数的模板形参由调用该函数的对象的类型确定。例如,当调用Queue 类型对象的 push 成员时,实例
化的 push 函数为 void Queue::push(const int &val)
类模板的成员函数只有为程序所用才进行实例化。如果某函数从未使用,则不会实例化该成员函数.
// instantiates Queue class and Queue::Queue()
Queue<string> qs;
qs.push("hello"); // instantiates Queue::push
|
非模板类型实参
template <int hi, int wid>
class Screen {
public:
// template nontype parameters used to initialize data members
Screen(): screen(hi * wid, '#'), cursor (0),
height(hi), width(wid) { }
// ...
private:
std::string screen;
std::string::size_type cursor;
std::string::size_type height, width;
};
|
调用时 Screen<16,24> MyS;
非类型模板实参必须是编译时常量表达式。类模板中友元声明,有三种:
1.普通非模板类或函数的友元声明,将友元关系授予明确指定的类或函数,其中非模板类或非模板函数可以是类模板的友元。
template <class Type> class Bar {
// grants access to ordinary, nontemplate class and function
friend class FooBar;
friend void fcn();
// ...
};
|
2.类模板或函数模板的友元声明,授予对友元所有实例的访问权,其中友元可以是类模板或函数模板
template <class Type> class Bar {
// grants access to Foo1 or templ_fcn1 parameterized by any type
template <class T> friend class Foo1;
template <class T> friend void templ_fcn1(const T&);
// ...
};
|
注意:这些友元声明使用与类本身
不同的类型形参。
Foo1 的任意实例都可以访问
Bar 的任意实例的私有元素,类似地,
temp_fcn1
的任意实例可以访问
Bar 的任意实例。对
Bar 的每个实例而言,
Foo1 或
temp1_fcn1 的所有实例都是友元。
3.只授予对类模板或函数模板的特定实例的访问权的友元声明,授予对特定实例的访问权
template <class T> class Foo2;
template <class T> void templ_fcn2(const T&);
template <class Type> class Bar {
// grants access to a single specific instance parameterized by char*
friend class Foo2<char*>;
friend void templ_fcn2<char*>(char* const &);
// ...
};
|
友元关系也只扩展到
Foo2 的形参类型为
char* 的特定实例,和只有形参类型为
char* 的函数实例是
Bar 类的友元。
最为常见的是下面这种,类模板参数和友元模板参数相同的
template <class T> class Foo3;
template <class T> void templ_fcn3(const T&);
template <class Type> class Bar {
// each instantiation of Bar grants access to the
// version of Foo3 or templ_fcn3 instantiated with the same type
friend class Foo3<Type>;
friend void templ_fcn3<Type>(const Type&);
// ...
};
|
如果没有事先告诉编译器该友元是一个模板,则编译器将认为该友元是一个普通非模板类或非模板函数
template <class T> class A;
template <class T> class B {
public:
friend class A<T>; // ok: A 有前向声明
friend class C; // ok: C 必须是普通类
template <class S> friend class D; // ok: 前有模板声明
friend class E<T>; // error: E 并没有声明为模板
friend class F<int>; // error: F 并没有声明为模板
};
|
阅读(1327) | 评论(0) | 转发(0) |