Chinaunix首页 | 论坛 | 博客
  • 博客访问: 299162
  • 博文数量: 148
  • 博客积分: 4365
  • 博客等级: 上校
  • 技术积分: 1566
  • 用 户 组: 普通用户
  • 注册时间: 2008-07-05 21:38
文章分类
文章存档

2014年(2)

2013年(45)

2012年(18)

2011年(1)

2009年(54)

2008年(28)

我的朋友

分类: C/C++

2009-09-26 12:28:38

有一个类模板如下,书上例子所示

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 的每个实例而言,Foo1temp1_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) |
给主人留下些什么吧!~~