關於《C++ Templates》

最近買了《C++ Templates》來看,書最開始部分闡述了關於此書的一些編程風格。本人感受很是好,有些地方以前一直容易搞混,這裏卻講述的很清楚。例如:ios

關於下面幾種風格的代碼:編程

void foo(const int &x);
void foo(const int& x);
void foo(int const &x);
void foo(int const& x);

對於上面四種用法,差異雖然不是很大,可是咱們更傾向於使用int const,而不是const int。函數

主要緣由:一、關於「恆定不變部分」指的是const限定符前面的部分。spa

記住這句話,相信諸如此類:int* const book_mark; 和 int const* book_mark; const int* book_mark; 的含義就不會搞錯了。指針

二、使用模板時一個很經常使用的語法替換原則。例如:code

 

typedef char* CHARS;
typedef CHARS const CPTR;  //指向char類型的常量指針,即指針不能改變

 

當咱們用CHARS進行替換後,第2個聲明的含義是不變的:blog

typedef char* const CPTR;

然而,若是咱們把const放在它所限定的類型的前面,那麼這個原則就再也不適用了。考慮以下:ci

typedef char* CHARS;
typedef const CHARS CPTR;   //指向char類型的常量指針,即指針不能改變

若是咱們替換CHARS後,第2個聲明將致使不一樣的含義:字符串

typedef const char* CPTR;   //指向常量char類型的指針

另外,對於本書的的前兩章,下面列了幾點重要的結論:string

  • 模板在編譯期間被編譯了兩次,分別發生在:

一、實例化以前,先檢查模板代碼以前,查看語法是否正確;在這裏會發現錯誤的語法,如遺漏分號等。

二、在實例化期間,檢查模板代碼,查看時候全部的調用都有效。在這裏會發現無效的調用,如該實例化類型不支持某些函數的調用等。

  • 實參演繹時,不容許進行自動類型轉換;每一個T都必須正確地匹配。如:
template<typename T>
inline T const& max(T const& a, T const& b);

max(4, 7);    //OK:兩個實參的類型都是int
max(4, 4.2)   //ERROR:第一個T是int,而第2個T是double

對於上面的錯誤,有三種方法能夠解決:

一、對實參進行強制類型轉換,使它們能夠互相匹配:

max( static_cast<double>(4), 4.2)   //OK

二、顯式指定(或者限定)T的類型:

max<double>(4, 4.2)   //OK

三、指定兩個參數能夠具備不一樣的類型。

下面從書中摘取了兩個例子,代碼比較簡單,以下所示:

一、函數模板重載的例子。

/**********************************************************
*   @filename: C++ templates example: function overloading
*   @author: JackyLiu
*   @data: 2013.6.25
***********************************************************/

#include <iostream>
#include <cstring>
#include <string>

//求兩個任意類型值的最大值/////////////////////////////
template <typename T>
inline T const& max(T const& a, T const& b)
{
    return a < b ? b : a;
}

//求兩個指針所指向值的最大值///////////////////////////
template<typename T>
inline T const& max(T* const& a, T* const& b)
{
    return *a < *b ? *b : *a;
}

//求兩個C字符串的最大者////////////////////////////////
inline char const* const& max(char const* const& a,
    char const* const& b)
{
    return std::strcmp(a,b) < 0 ? b : a;
}

int main(int argc, char *argv[])
{
    int a = 7;
    int b = 42;
    std::cout<< ::max(a, b)<< std::endl;   //max()求兩個int值的最大值

    std::string s = "hey";
    std::string t = "you";
    std::cout<< ::max(s,t)<< std::endl;    //max()求兩個std::string類型的最大值

    int *p1 = &b;
    int *p2 = &a;
    std::cout<< ::max(p1,p2)<< std::endl;   //max()求兩個指針所指向值得最大者

    char const* s1 = "David";
    char const* s2 = "Nico";
    std::cout<< ::max(s1, s2)<< std::endl;  //max()求兩個c字符串的最大值

    int i;
    std::cin>> i;
}

二、類模板的例子:

stack3.hpp

#include <vector>
#include <stdexcept>

/**
*    缺省模板實參
*/
template<typename T, typename CONT = std::vector<T> >
class Stack
{
private:
    CONT elems;
public:
    void push(T const&);
    void pop();
    T top() const;
    bool empty() const
    {
        return elems.empty();
    }
};

template<typename T, typename CONT>
void Stack<T, CONT>::push(T const& elem)
{
    elems.push_back(elem);
}

template<typename T, typename CONT>
void Stack<T, CONT>::pop()
{
    if(elems.empty())
        throw std::out_of_range("Stack<>::pop(): empty stack");
    elems.pop_back();
}

template<typename T, typename CONT>
T Stack<T, CONT>::top() const
{
    if(elems.empty())
        throw std::out_of_range("Stack<>::pop(): empty stack");
    return elems.back();
}

main.cpp

/*******************************************************************
*   @filename: the implementation of the class template of stack
*   @author: JackyLiu
*   @date: 2013.6.25
********************************************************************/

#include <iostream>
#include <deque>
#include <string>
#include <cstdlib>
//#include "stack1.hpp"
#include "stack3.hpp"

int main(int argc, char *argv[])
{
    /*********************************************************************
    try
    {
        Stack<int> intStack;  //元素類型爲int的棧
        Stack<std::string> stringStack;  //元素類型爲字符串的棧

        //使用int棧
        intStack.push(7);
        std::cout << intStack.top() << std::endl;

        //使用string棧
        stringStack.push("hello");
        std::cout << stringStack.top() << std::endl;
        stringStack.pop();
        stringStack.pop();
    }
    catch(std::exception const& ex)
    {
        std::cerr << "Exception: " << ex.what() << std::endl;

        int i;
        std::cin >> i;

        return EXIT_FAILURE;    //程序退出,且帶有ERROR標記
    }
    */

    try
    {
        //int棧
        Stack<int> intStack;

        //double棧,它使用std::deque來管理元素
        Stack<double, std::deque<double> > dblStack;

        //使用int棧
        intStack.push(7);
        std::cout << intStack.top() << std::endl;
        intStack.pop();

        //使用double棧
        dblStack.push(42.42);
        std::cout << dblStack.top() << std::endl;
        dblStack.pop();
        dblStack.pop();
    }
    catch(std::exception const& ex)
    {
        std::cerr << "Exception: " << ex.what() << std::endl;

        int i;
        std::cin >> i;

        return EXIT_FAILURE;   //退出程序,且有ERROR標記
    }
}
相關文章
相關標籤/搜索