类模板

内容简介

类模板用于定义类型可变的类。STL 容器就是最典型的类模板,例如 std::vector<int>std::map<std::string, int>

用法

基本语法:

template <typename Name, typename Age>
class Person {
public:
    Person(Name name, Age age)
        : name_(name), age_(age)
    {
    }
 
    void show() const
    {
        std::cout << name_ << " " << age_ << '\n';
    }
 
private:
    Name name_;
    Age age_;
};

使用方式:

Person<std::string, int> p("Alice", 18);
p.show();

类模板和函数模板的区别

类模板通常需要显式指定类型

Person<std::string, int> p("Alice", 18);

旧标准中类模板没有自动类型推导。C++17 起有 CTAD,但初学阶段建议先显式写清类型。

类模板可以有默认模板参数

template <typename Name, typename Age = int>
class Person {
public:
    Person(Name name, Age age) : name_(name), age_(age) {}
 
private:
    Name name_;
    Age age_;
};
 
Person<std::string> p("Bob", 20);

类模板成员函数调用时机

类模板的成员函数通常在被使用时才实例化。

class Person1 {
public:
    void show1() {}
};
 
class Person2 {
public:
    void show2() {}
};
 
template <typename T>
class MyClass {
public:
    T obj;
 
    void func1()
    {
        obj.show1();
    }
 
    void func2()
    {
        obj.show2();
    }
};
 
MyClass<Person1> m;
m.func1();  // 正确
// m.func2();  // 错误:Person1 没有 show2,但只有调用 func2 时才暴露

类模板对象做函数参数

直接指定类型:

void print_person(Person<std::string, int>& p)
{
    p.show();
}

参数模板化:

template <typename Name, typename Age>
void print_person(Person<Name, Age>& p)
{
    p.show();
}

整个类型模板化:

template <typename T>
void print_any(T& value)
{
    value.show();
}

类模板与继承

继承类模板时,父类模板参数必须能确定:

template <typename T>
class Base {
    T value_;
};
 
class Son : public Base<int> {
};
 
template <typename T1, typename T2>
class Son2 : public Base<T2> {
    T1 obj_;
};

最佳代码实践

  • 类模板适合保存或处理“类型可变但结构一致”的对象。
  • 模板参数名称要表达含义,不要所有参数都叫 T1T2
  • 能用标准库类模板时优先用标准库,例如 std::vectorstd::optionalstd::unique_ptr
  • 初学阶段显式写模板实参,熟悉后再使用 CTAD。

错误用法

Person p("Alice", 18);  // C++17 前错误;初学阶段也不建议依赖推导
template <typename T>
class Box {
    T value_;
};
 
Box box;  // 错误:无法知道 T 是什么

注意事项

  • 类模板实例化后才是真正的类型。
  • Person<std::string, int>Person<std::string, double> 是不同类型。
  • 类模板成员函数分文件写法要特别小心,见 cpp类模板分文件编写