#include <iostream>
#include <vector>
// 模板基类
template <typename T>
class Base {
public:
T value;
Base(T val) : value(val) {}
};
// 派生模板类
template <typename T>
class Derived : public Base<T> {
public:
std::vector<T> vec;
Derived(T val, const std::vector<T>& v) : Base<T>(val), vec(v) {}
};
// 针对T为int类型的模板特化
template <>
class Derived<int> : public Base<int> {
public:
std::vector<int> vec;
Derived(int val) : Base<int>(val) {
for (int i = 1; i <= 10; ++i) {
vec.push_back(i);
}
}
};
模板类初始化成员列表与继承、模板特化之间相互影响的要点:
- 初始化成员列表与继承:
- 在派生类构造函数的初始化成员列表中,首先要调用基类的构造函数来初始化基类部分的成员变量。例如在
Derived<T>
的构造函数 Derived(T val, const std::vector<T>& v) : Base<T>(val), vec(v) {}
中,Base<T>(val)
先初始化基类 Base<T>
的 value
成员变量,然后才初始化派生类自己的 vec
成员变量。这是因为基类部分是派生类对象的一部分,必须先构造基类部分,才能继续构造派生类新增的成员。
- 模板特化与初始化成员列表:
- 模板特化可以针对特定的模板参数类型提供不同的实现。在
Derived<int>
的特化版本中,构造函数采用了不同的初始化方式。虽然仍然需要先调用基类构造函数 Base<int>(val)
初始化基类成员 value
,但对于 vec
成员变量,它采用了特定的填充 1 到 10 整数的逻辑,而不是像通用模板那样依赖外部传入的 std::vector<T>
进行初始化。模板特化使得我们可以为特定类型定制类的行为,包括构造函数中的初始化逻辑。
- 保持一致性:
- 无论是通用模板还是模板特化,都要遵循类继承的基本规则,即先构造基类再构造派生类自己的成员。同时,在模板特化时,虽然可以改变成员变量的初始化逻辑,但也要确保与基类的初始化和整体类的设计目标保持一致,以避免产生逻辑错误或难以维护的代码。