从放弃到重启 C++—类模板

218 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第20天,点击查看活动详情

  • 与函数模板类似,类也可以通过参数,从而可以构建出一族不同类型的类实例(对象)
  • 类模板实参可以是某一类型或常量(仅限于 int 和 enum)

类模板的声明

  • 声明类模板与声明函数模板类似,在定义类型参数时候可以使用关键字 classtypename 来定义。
  • 在类模板内部,成员变量或者成员函数都可以使用 T 当做类型,这与其他类型并没有任何区别
  • 除了 Copy 构造函数之外,如果在类模板中需要使用到这个类本身,比如定义 operator=,那么应该使用其完整的定义(MyStack<T>),而不是省略类型 T, 如下面的例子所示:
template <class T>
class className {
  private:
    T var;
    ... .. ...
  public:
    T functionName(T arg);
    ... .. ...
};
  • 类模板定义,也是通过关键字 template 随后跟着模板参数,模板参数放在一对尖括号<>
  • 其中模板参数 T 是类型参数,接收一个类型
const std::size_t DefaultStackSize = 1024;

template<typename T, std::size_t n = DefaultStackSize > class MyStack {
public:
    void Push(const T const& elem);
    int Pop(T& elme);
    int Top(T& elem) const;

private:
    std::vector<T> m_Members;
    std::size_t m_nMaxSize = n;

};
  • T 可以是任意类型,也就是模板类型参数

  • 模板实参也可以是一个 intenum 类型的常量,这里 size_t 本质也就是一个 int 类型

  • n 是编译时定义的常量,可以定义模板时为其指定默认值

  • size_t 类型的成员变量可以用 n 初始化

  • 类模板的实现,要定义一个类模板的成员函数,则要指明其是一个模板函数,例如 Push 函数的定义应当如下:

template<typename T,std::size_t nMaxSize>
void MyStack<T, nMaxSize>::Push(const T const& element)
{
    if (m_Members.size() >= m_nMaxSize) {
        return;
    }

    m_Members.push_back(element);
}

如果要是把成员函数写在声明体之外,就需要模板类需要添加上 template<typename T,std::size_t nMaxSize>

类模板的使用

MyStack<int> my_stack;
my_stack.Push(1);
MyStack<MyStack<int> > intMyStackStack;
  • MyStack<int> my_stack 定义了一个类型为 intMyStack 大小默认值为 1024,
  • 可以在初始化时候传入 MyStack<int, 100> my_stack_2; 来定义类型为 int 大小为 100MyStack 需要注意 MyStack<MyStack<int> > intMyStackStack; 需要在 > 两个之间留有一个空格,不要>>这样写,如果这样写可能会认为操作符。

多参数模板

template <class T, class U, class V = int>
class ClassName {
  private:
    T member1;
    U member2;
    V member3;
    ... .. ...
  public:
    ... .. ...
};
#include <iostream>
using namespace std;

// 类模板带有多个参数以及类型参数带有默认值
template <class T, class U, class V = char>
class ClassTemplate {
   private:
    T var1;
    U var2;
    V var3;

   public:
    ClassTemplate(T v1, U v2, V v3) : var1(v1), var2(v2), var3(v3) {}  // constructor

    void printVar() {
        cout << "var1 = " << var1 << endl;
        cout << "var2 = " << var2 << endl;
        cout << "var3 = " << var3 << endl;
    }
};

int main() {
    // 创建一个使用 int, double 和 char 类型的模板
    ClassTemplate<int, double> obj1(2, 3.2, 'c');
    cout << "obj1 values: " << endl;
    obj1.printVar();

    // 创建一个使用 int, double 和 bool 类型的模板
    ClassTemplate<double, char, bool> obj2(8.2, 'a', false);
    cout << "\nobj2 values: " << endl;
    obj2.printVar();

    return 0;
}
template <class T, class U, class V = char>
class ClassTemplate {
  // code  
};

这里创建了一个模板类,类名称为 ClassTemplate 并带有三个参数,其中一个参数带有默认值

  • class V = char 表示 v 类型参数默认值为 char 类型,然后模板定义 3 个类型参数分别为成员变量的类型

内嵌模板类

模板可以被定义在类或类模板中,在这种情况下,成员模板。作为类的成员模板被称为嵌套类模板。属于函数的成员模板将在成员函数模板中讨论。

class Tut
{
   template<class T>
   struct Description
   {
       T m_val;
       Description(T t) :m_val(t) {}
   };

   Description<int> mCourse;
   Description<char> mTitle;

public:
    Tut(int i, char c): mCourse(i), mTitle(c){}
    void print()
    {
        std::cout << "test" << std::endl;
    }
};