美文网首页C++
C++ 模板开发

C++ 模板开发

作者: JasonChen8888 | 来源:发表于2018-03-08 14:48 被阅读37次

    C++模板开发分为两类:

    • 模板函数开发

    • 模板类开发

    模板函数语法:

    template <class type> ret-type func-name(parameter list)
    {
       // 函数的主体
    }
    

    template是关键字,<class type>表示指定的类型(类似java的泛型),ret-type表示返回类型
    func-name(parameter list):函数名称和参数

    • 例子:
    #include <iostream>
    #include <string>
     
    using namespace std;
     //模板函数
    template <typename T>
    inline T const& Max (T const& a, T const& b) 
    { 
        return a < b ? b:a; 
    } 
    int main ()
    {
     
        int i = 39;
        int j = 20;
        cout << "Max(i, j): " << Max(i, j) << endl; 
     
        double f1 = 13.5; 
        double f2 = 20.7; 
        cout << "Max(f1, f2): " << Max(f1, f2) << endl; 
     
        string s1 = "Hello"; 
        string s2 = "World"; 
        cout << "Max(s1, s2): " << Max(s1, s2) << endl; 
     
       return 0;
    }
    

    模板类语法:

    template <class type> class class-name {
    ...
    }
    

    template是关键字,<class type>表示指定的类型,class-name表示类名
    例子:

    #include <iostream>
    #include <vector>
    #include <cstdlib>
    #include <string>
    #include <stdexcept>
     
    using namespace std;
     
    template <class T>
    class Stack { 
      private: 
        vector<T> elems;     // 元素 
     
      public: 
        void push(T const&);  // 入栈
        void pop();               // 出栈
        T top() const;            // 返回栈顶元素
        bool empty() const{       // 如果为空则返回真。
            return elems.empty(); 
        } 
    }; 
     
    template <class T>
    void Stack<T>::push (T const& elem) 
    { 
        // 追加传入元素的副本
        elems.push_back(elem);    
    } 
     
    template <class T>
    void Stack<T>::pop () 
    { 
        if (elems.empty()) { 
            throw out_of_range("Stack<>::pop(): empty stack"); 
        }
        // 删除最后一个元素
        elems.pop_back();         
    } 
     
    template <class T>
    T Stack<T>::top () const 
    { 
        if (elems.empty()) { 
            throw out_of_range("Stack<>::top(): empty stack"); 
        }
        // 返回最后一个元素的副本 
        return elems.back();      
    } 
     
    int main() 
    { 
        try { 
            Stack<int>         intStack;  // int 类型的栈 
            Stack<string> stringStack;    // string 类型的栈 
     
            // 操作 int 类型的栈 
            intStack.push(7); 
            cout << intStack.top() <<endl; 
     
            // 操作 string 类型的栈 
            stringStack.push("hello"); 
            cout << stringStack.top() << std::endl; 
            stringStack.pop(); 
            stringStack.pop(); 
        } 
        catch (exception const& ex) { 
            cerr << "Exception: " << ex.what() <<endl; 
            return -1;
        } 
    }
    

    上面的模板函数和模板类的例子,都是定义和声明在同一个文件中,但是如果按照传统的C++类开发,类的声明放H头文件,定义方法CPP源文件,这个时候编译会报错,提示成员函数未定义。这个问题在个人开发中一直不解,最后在网上搜索找到了合理的解释 :

    在分离式编译的环境下,编译器编译某一个.cpp文件时并不知道另一个.cpp文件的存在,也不会去查找[当遇到未决符号时它会寄希望于连接器]。这种模式在没有模板的情况下运行良好,但遇到模板时就傻眼了,因为模板仅在需要的时候才会具现化出来,所以,当编译器只看到模板的声明时,它不能具现化该模板,只能创建一个具有外部连接的符号并期待连接器能够将符号的地址决议出来。然而当实现该模板的.cpp文件中没有用到模板的具现体时,编译器懒得去具现,所以,整个工程的.obj中就找不到一行模板具现体的二进制代码,于是连接器也黔
    总之,在模板开发过程中,声明和定义必须放在一个文件中。当然,这个问题,也是有解决方案的,可以参考C++ 模板类的声明与实现分离问题

    参考文献http://blog.csdn.net/u012750314/article/details/52770847
    这是模板分离开发的实现可以借鉴:
    https://www.jianshu.com/p/3a7a41d46645

    相关文章

      网友评论

        本文标题:C++ 模板开发

        本文链接:https://www.haomeiwen.com/subject/uqkyfftx.html