美文网首页
第二章:模板类

第二章:模板类

作者: 找不到工作 | 来源:发表于2020-12-26 13:46 被阅读0次

    与函数类似,类也可以使用模板参数。典型例子就是cpp标准库里的各种容器。

    Takeaways:

    • 模板类的成员函数只在被使用到时才实例化

    2.1 例子:栈

    #include <vector>
    
    
    template<typename T>
    class Stack {
    
    private:
      std::vector<T> elems_;
    
    public:
      void push(const T& elem);
      void pop();
      T const& top() const;
      bool empty() const {return elems_.empty();}
    };
    
    
    template<typename T>
    void Stack<T>::push(const T& elem) {
      // append copy of passed elem
      elems_.push_back(elem);
    }
    
    template<typename T>
    void Stack<T>::pop() {
      assert(!elems_.empty());
      elems_.pop_back();
    }
    
    template<typename T>
    T const& Stack<T>::top() const {
      assert(!elems_.empty());
      return elems_.back();
    }
    

    没什么特别需要注意的,下面的代码是如何使用:

    #include "stack1.hpp"
    
    #include <string>
    #include <iostream>
    
    int main(int argc, char const *argv[]) {
      Stack<int> intStack;
      Stack<std::string> stringStack;
    
      intStack.push(7);
      std::cout<<intStack.top()<<std::endl;
    
      stringStack.push("hello");
      std::cout<<stringStack.top()<<std::endl;
      stringStack.pop();
      return 0;
    }
    

    对于模板类,成员函数只在被使用到时才实例化。如上代码中,pop()只对stringStack实例化了,因为它并未被intStack调用。

    2.3 模板类的部分使用

    由于成员函数只有被调用才会实例化,我们不需要保证每个成员函数都对某个类型可用。

    例如,我们可以给 stack 添加一个 str() 方法来返回自身的字符串。

    template<typename T>
    std::string Stack<T>::str() const {
      std::stringstream ss;
    
      ss << '[';
      for (int i=0; i<elems_.size(); i++) {
        ss << elems_[i];
        if (i!=elems_.size()-1) {
          ss << ',';
        }
      }
      ss << ']';
    
      return ss.str();
    }
    

    不支持 << 操作符的类型同样可以使用这个模板类。

      Stack< std::pair<int, int> > pairStack;
      pairStack.push({4, 5});
      pairStack.push({6, 7});
      pairStack.pop();
      std::cout<<pairStack.top().first<<std::endl; // output 4
      std::cout<<pairStack.top().second<<std::endl; // output 5
    

    但是如果尝试使用 str() 函数就会报错:

    std::cout<<pairStack.str()<<std::endl; // compile error
    

    2.4 友元

    略,与模板关系不大

    2.5 模板类的特化

    类似于模板函数的重载,我们可以给出指定模板类的某些模板参数进行特化。特化可以使我们为某个模板实例单独实现一套逻辑。

    为了特化模板类,我们必须用 template<>,并使用具体的类替换 T。如下就是对 std::string 的特化:

    template<>
    class Stack<std::string> {
      ...
    };
    

    类似的,我们也需要把成员函数中所有的 T 换为 std::string

    2.6 部分特化

    我们也可以使模板类“部分”特化来处理一类的类型。例如,对指针类型:

    template<typename T>
    class Stack<T*> {
      ...
    };
    

    注意,这里我们仍然保留了 template<typename T>, 但是对指针进行了特化:class Stack<T*>

    多参数的部分特化

    对于多个模板参数的模板类,例如:

    template<typename T1, typename T2>
    class MyClass {
      ...
    };
    

    我们可以进行多种特化:

    // partial specialization: both template parameters have same type
    template<typename T>
    class MyClass<T, T> {
      ...
    };
    
    // partial specialization: second type is int
    template<typename T>
    class MyClass<T, int> {
      ...
    };
    
    // partial specialization: both parameters are pointers
    template<typename T1, typename T2>
    class MyClass<T1*, T2*> {
      ...
    };
    

    对于不同的调用,会匹配不同的特化:

    MyClass<int, float> mif;  // uses MyClass<T1, T2>
    MyClass<float, float> mff;  // uses MyClass<T, T>
    MyClass<float, int> mfi;  // uses MyClass<T, int>
    MyClass<int*, float*> mpp;  // uses MyClass<T1*, T2*>
    

    但是如果某种类型可以匹配多种特化,则会报错:

    MyClass<int, int> mii; // ERROR, matches <T, T> and <T, int>
    MyClass<int*, int*> mpp; // ERROR, matches <T, T> and <T1*, T2*>
    

    遇到这种情况,需要添加更佳匹配的特化,例如:

    // partial specialization: both parameters are pointers
    template<typename T>
    class MyClass<T*, T*> {
      ...
    };
    

    2.7 默认模板参数

    2.8 类型别名

    using 的用法,略

    2.9 模板参数类型推断

    C++17 新引入的功能:

    Stack<int> intStack1;
    Stack<int> intStack2 = intStack1; // OK in all versions
    Stack intStack3 = intStack1; // OK since C++17
    

    语法糖,略。

    相关文章

      网友评论

          本文标题:第二章:模板类

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