码迷,mamicode.com
首页 > 编程语言 > 详细

《C++ Primer Plus》14.4 类模板 学习笔记

时间:2016-07-14 10:09:06      阅读:239      评论:0      收藏:0      [点我收藏+]

标签:

14.4.1 定义类模板
下面以第10章的Stack类为基础来建立模板。原来的类声明如下:
typedef unsigned long Item;

class Stack
{
private:
    enum {MAX = 10};    // constant specific to class
    Item items[MAX];    // holds stack items
    int top;            // index for top stack item
public:
    Stack();
    bool isempty() const;
    bool isfull() const;
    // push() returns false if stack already is full, true otherwise
    bool push(const Item & item);   // add item to stack
    // pop() returns false if stack already is empty, true otherwise
    bool pop(Item & item);          // pop top into item
};
采用模板时,将使用模板定义替换Stack声明,使用模板成员函数替换Stack的成员函数。和模板函数一样,模板类以下面这样的代码开头:
template <class Type>
关键字template告诉编译器,将要定义一个模板。尖括号中的内容相当于函数的参数列表。可以把关键字class看作是变量的类型名,该变量接受类型作为其值,把Type看作是改变量的名称。
这里使用class并不意味着Type必须是一个类;而只是表明Type是一个通用的类型说明符,在使用模板时,将使用实际的类型替换它。较新的C++实现允许在这种情况下使用不太容易混淆的关键字typename代替class:
template <typename Type>    // new choice
可以使用自己的泛型名代替Type,其命名规则与其他标识符相同。当前比较流行的选项包括T和Type。在模板定义中,可以使用泛型名来标识要存储在栈中的类型。对于Stack来说,这意味着将声明中所有的typedef标识符Item替换为Type。例如,
Item items[MAX];    // holds stack items
应改为:
Type items[MAX];    // holds stack items
同样,可以使用模板成员函数替换原有类的类方法。每个函数头都将以相同的模板声明打头:
template <class Type>
同样应使用泛型名Type替换typedef标识符Item。另外,还需要将限定符从Stack::改为Stack<Type>::。例如,
bool Stack::push(const Item & item)
{
...
}
应改为:
template <class Type>       // or template <typename Type>
bool Stack<Type>::push(const Type & item)
{
...
}
如果在类声明中定义了方法(内联定义),则可以省略模板前缀和类限定符。
程序清单14.13列出了类模板和成员函数。知道这些模板不是类和成员函数定义至关重要。它们是C++编译器指令,说明了如何生成类和成员函数定义。模板的具体是现——如用来处理string对象的栈类——被称为实例化(instantiation)或具体化(specialization)。不能将模板成员函数放在独立的实现文件中。由于模板不是函数,它们不能单独编译。模板必须与特定的模板实例化请求一起使用。为此,最简单的方法是将所有模板信息放在一个头文件中,并在要使用这些模板的文件中包含该文件头。
程序清单14.13 stacktp.h

// stacktp.h -- a stack template
#ifndef STACKTP_H_
#define STACKTP_H_

template <class Type>
class Stack
{
private:
    enum {MAX = 10};    // constant specific to class
    Type items[MAX];    // holds stack items
    int top;            // index for top stack item
public:
    Stack();
    bool isempty();
    bool isfull();
    bool push(const Type & item);   // add item to stack
    bool pop(Type & item);          // pop top into item
};

template <class Type>
Stack<Type>::Stack()
{
    top = 0;
}

template <class Type>
bool Stack<Type>::isempty()
{
    return top == 0;
}

template <class Type>
bool Stack<Type>::isfull()
{
    return top == MAX;
}

template <class Type>
bool Stack<Type>::push(const Type & item)
{
    if (top < MAX)
    {
        items[top++] = item;
        return true;
    }
    else
        return false;
}

template <class Type>
bool Stack<Type>::pop(Type & item)
{
    if (top > 0)
    {
        item = items[--top];
        return true;
    }
    else
        return false;
}

#endif // STACKTP_H_


14.4.2 使用模板类
仅在程序包含模板并不能生成模板类,而必须请求实例化。为此,需要生命一个类型为模板类的对象,方法是使用所需的具体类型替换泛型名。例如,下面的代码创建两个栈,一个用于存储int,另一个用于存储string对象:
Stack<int> kernels;        // create a stack of ints
Stack<string> colonels;        // create a stack of string objects
看到上述声明后,编译器将按Stack<Type>模板来生成两个独立的类声明和两组独立的类方法。
程序清单14.14修改了原来的栈测试程序(程序清单11.12),使用字符串而不是unsigned long值作为订单ID。
程序清单14.14 stacktem.cpp

// stacktem.cpp -- testing the template stack class
#include <iostream>
#include <string>
#include <cctype>
#include "stacktp.h"
using std::cin;
using std::cout;

int main()
{
    Stack<std::string> st;  // create an empty stack
    char ch;
    std::string po;
    cout << "Please enter A to add a purchase order.\n"
         << "P to process a PO, or Q to quit.\n";
    while (cin >> ch && std::toupper(ch) != Q)
    {
        while (cin.get() != \n)
            continue;
        if (!std::isalpha(ch))
        {
            cout << \a;
            continue;
        }
        switch (ch)
        {
            case A:
            case a:   cout << "Enter a PO number to add: ";
                        cin >> po;
                        if (st.isfull())
                            cout << "stack already full\n";
                        else
                            st.push(po);
                        break;
            case P:
            case p:   if (st.isempty())
                            cout << "stack already empty\n";
                        else {
                            st.pop(po);
                            cout << "PO #" << po << " popped\n";
                            break;
                        }
        }
        cout << "Please enter A to add a purchase order.\n"
             << "P to process a PO, or Q to quit.\n";
    }
    cout << "Bye\n";
    return 0;
}

效果:

Please enter A to add a purchase order.
P to process a PO, or Q to quit.
A
Enter a PO number to add: moonlightpoet
Please enter A to add a purchase order.
P to process a PO, or Q to quit.
A
Enter a PO number to add: moonlit
Please enter A to add a purchase order.
P to process a PO, or Q to quit.
P
PO #moonlit popped
Please enter A to add a purchase order.
P to process a PO, or Q to quit.
P
PO #moonlightpoet popped
Please enter A to add a purchase order.
P to process a PO, or Q to quit.
P
stack already empty
Please enter A to add a purchase order.
P to process a PO, or Q to quit.
Q
Bye

 

《C++ Primer Plus》14.4 类模板 学习笔记

标签:

原文地址:http://www.cnblogs.com/moonlightpoet/p/5669239.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!