MST

星途 面试题库

面试题:C++ 复杂模板类构造函数重载与调用顺序

设计一个模板类 `TemplateClass`,该模板类接受两个类型参数。模板类具有多个重载的构造函数,包括默认构造函数、接受一个类型为其中一个模板参数的构造函数以及接受两个不同类型参数的构造函数。同时,设计一个继承自 `TemplateClass` 的模板子类 `SubTemplateClass`,也具有多个重载构造函数。在 `main` 函数中,使用不同的模板参数实例化 `SubTemplateClass` 并创建对象,详细说明在整个过程中,构造函数的重载情况以及调用顺序,并且要考虑模板实例化过程对构造函数调用顺序的影响。
31.1万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试
#include <iostream>

// 模板类 TemplateClass 定义
template<typename T1, typename T2>
class TemplateClass {
public:
    // 默认构造函数
    TemplateClass() {
        std::cout << "TemplateClass 默认构造函数被调用" << std::endl;
    }

    // 接受一个类型为 T1 的构造函数
    TemplateClass(const T1& value1) : data1(value1) {
        std::cout << "TemplateClass 接受一个 T1 类型参数的构造函数被调用" << std::endl;
    }

    // 接受两个不同类型参数的构造函数
    TemplateClass(const T1& value1, const T2& value2) : data1(value1), data2(value2) {
        std::cout << "TemplateClass 接受一个 T1 和一个 T2 类型参数的构造函数被调用" << std::endl;
    }

protected:
    T1 data1;
    T2 data2;
};

// 模板子类 SubTemplateClass 定义
template<typename T1, typename T2>
class SubTemplateClass : public TemplateClass<T1, T2> {
public:
    // 默认构造函数
    SubTemplateClass() {
        std::cout << "SubTemplateClass 默认构造函数被调用" << std::endl;
    }

    // 接受一个类型为 T1 的构造函数
    SubTemplateClass(const T1& value1) : TemplateClass<T1, T2>(value1) {
        std::cout << "SubTemplateClass 接受一个 T1 类型参数的构造函数被调用" << std::endl;
    }

    // 接受两个不同类型参数的构造函数
    SubTemplateClass(const T1& value1, const T2& value2) : TemplateClass<T1, T2>(value1, value2) {
        std::cout << "SubTemplateClass 接受一个 T1 和一个 T2 类型参数的构造函数被调用" << std::endl;
    }
};

int main() {
    // 使用不同模板参数实例化 SubTemplateClass 并创建对象
    SubTemplateClass<int, double> obj1;
    SubTemplateClass<int, double> obj2(10);
    SubTemplateClass<int, double> obj3(10, 3.14);

    return 0;
}

构造函数重载情况及调用顺序

  1. obj1 的创建
    • 首先调用 TemplateClass<int, double> 的默认构造函数,因为 SubTemplateClass 的默认构造函数会隐式调用父类的默认构造函数。
    • 然后调用 SubTemplateClass<int, double> 的默认构造函数。
    • 输出:
      TemplateClass 默认构造函数被调用
      SubTemplateClass 默认构造函数被调用
      
  2. obj2 的创建
    • 调用 TemplateClass<int, double> 的接受一个 int 类型参数的构造函数,因为 SubTemplateClass 的接受一个 int 类型参数的构造函数显式调用了父类相应的构造函数。
    • 然后调用 SubTemplateClass<int, double> 的接受一个 int 类型参数的构造函数。
    • 输出:
      TemplateClass 接受一个 T1 类型参数的构造函数被调用
      SubTemplateClass 接受一个 T1 类型参数的构造函数被调用
      
  3. obj3 的创建
    • 调用 TemplateClass<int, double> 的接受一个 int 和一个 double 类型参数的构造函数,因为 SubTemplateClass 的接受一个 int 和一个 double 类型参数的构造函数显式调用了父类相应的构造函数。
    • 然后调用 SubTemplateClass<int, double> 的接受一个 int 和一个 double 类型参数的构造函数。
    • 输出:
      TemplateClass 接受一个 T1 和一个 T2 类型参数的构造函数被调用
      SubTemplateClass 接受一个 T1 和一个 T2 类型参数的构造函数被调用
      

模板实例化对构造函数调用顺序的影响

在上述代码中,模板实例化在编译时发生。编译器根据 main 函数中使用的具体类型(如 intdouble)生成相应的 TemplateClassSubTemplateClass 类的实例。构造函数的调用顺序遵循类继承体系中的规则,即先调用父类的构造函数,再调用子类的构造函数。模板实例化本身并不改变构造函数的调用顺序,只是根据实际类型生成相应的类定义及构造函数定义,使得在运行时能正确执行构造函数。