• 关于《C++ Templates》


    最近买了《C++ Templates》来看,书最开始部分阐述了关于此书的一些编程风格。本人感觉非常好,有些地方之前一直容易搞混,这里却讲述的很清楚。例如:

    关于下面几种风格的代码:

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

    对于上面四种用法,差别虽然不是很大,但是我们更倾向于使用int const,而不是const int。

    主要原因:1、关于“恒定不变部分”指的是const限定符前面的部分。

    记住这句话,相信诸如此类:int* const book_mark; 和 int const* book_mark; const int* book_mark; 的含义就不会搞错了。

    2、使用模板时一个很常用的语法替换原则。例如:

    typedef char* CHARS;
    typedef CHARS const CPTR;  //指向char类型的常量指针,即指针不能改变

    当我们用CHARS进行替换后,第2个声明的含义是不变的:

    typedef char* const CPTR;

    然而,如果我们把const放在它所限定的类型的前面,那么这个原则就不再适用了。考虑如下:

    typedef char* CHARS;
    typedef const CHARS CPTR;   //指向char类型的常量指针,即指针不能改变

    如果我们替换CHARS后,第2个声明将导致不同的含义:

    typedef const char* CPTR;   //指向常量char类型的指针

    另外,对于本书的的前两章,下面列了几点重要的结论:

    • 模板在编译期间被编译了两次,分别发生在:

    1、实例化之前,先检查模板代码之前,查看语法是否正确;在这里会发现错误的语法,如遗漏分号等。

    2、在实例化期间,检查模板代码,查看时候所有的调用都有效。在这里会发现无效的调用,如该实例化类型不支持某些函数的调用等。

    • 实参演绎时,不允许进行自动类型转换;每个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

    对于上面的错误,有三种方法可以解决:

    1、对实参进行强制类型转换,使它们可以互相匹配:

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

    2、显式指定(或者限定)T的类型:

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

    3、指定两个参数可以具有不同的类型。

    下面从书中摘取了两个例子,代码比较简单,如下所示:

    1、函数模板重载的例子。

    /**********************************************************
    *   @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;
    }

    2、类模板的例子:

    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标记
        }
    }
    当你心中只有一个目标时,全世界都会给你让路!Read more! Write more! Practise more! 新浪微博:liu_军
  • 相关阅读:
    MongoDB 基础命令行
    AngularJS 监控对象属性:$watch和$digest
    AngularJS核心01:如何启动
    免费的编程中文书籍索引
    AngularJS Intellisense in Visual Studio 2012
    SQL Server中Rowcount与@@Rowcount
    VS 关于 .sln 文件和 .suo 文件
    Dart 基础重点截取 Dart 2 20180417
    io.netty.resolver.dns.DnsNameResolverContext
    mybatis BigDecimal Double Long 的坑爹事
  • 原文地址:https://www.cnblogs.com/liu-jun/p/3157389.html
Copyright © 2020-2023  润新知