MST

星途 面试题库

面试题:C++模板类中初始化成员列表与继承及模板特化的综合运用

假设有一个模板基类 `Base<T>`,包含一个模板类型的成员变量 `value`,通过初始化成员列表在构造函数中初始化 `value`。然后有一个派生模板类 `Derived<T>` 继承自 `Base<T>`,`Derived<T>` 新增一个 `std::vector<T>` 类型的成员变量 `vec`。请实现 `Derived<T>` 的构造函数,使用初始化成员列表对 `vec` 进行初始化,并且针对 `T` 为 `int` 类型进行模板特化,在特化版本中对 `vec` 进行特殊初始化(例如填充 1 到 10 的整数)。阐述在这个过程中模板类初始化成员列表与继承、模板特化之间相互影响的要点。
25.2万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试
#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);
        }
    }
};

模板类初始化成员列表与继承、模板特化之间相互影响的要点:

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