MST

星途 面试题库

面试题:C++模板类派生新类在复杂场景下的代码结构优化

在一个大型项目中,有一个模板类层次结构。`template <typename T, typename Policy> class CoreTemplate { /* 复杂逻辑,依赖Policy的一些策略方法 */ };` 现有多个派生类从`CoreTemplate`派生,例如`template <typename T> class Derived1 : public CoreTemplate<T, Policy1> { /*... */ };`,`template <typename T> class Derived2 : public CoreTemplate<T, Policy2> { /*... */ };` 等。现在项目需求发生变化,需要在所有派生类中添加一个通用的功能,该功能依赖于`CoreTemplate`中的部分状态,但实现细节因派生类而异。请设计一种优化的代码结构来实现这个需求,既要考虑代码的可维护性,又要避免重复代码,并且说明在这种设计下如何处理模板参数的类型兼容性和编译期优化。
45.9万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试
  1. 设计代码结构
    • 首先,在CoreTemplate类中定义获取所需状态的接口方法。例如:
    template <typename T, typename Policy>
    class CoreTemplate {
    public:
       // 假设这是获取部分状态的方法
       auto getRequiredState() const {
          // 返回与Policy相关的部分状态
          return Policy::getState(*this);
       }
       // 复杂逻辑,依赖Policy的一些策略方法
       //...
    };
    
    • 然后,在基类CoreTemplate中定义一个虚函数(可以是纯虚函数,如果派生类实现完全不同),用于实现这个通用功能的接口。例如:
    template <typename T, typename Policy>
    class CoreTemplate {
    public:
       auto getRequiredState() const {
          return Policy::getState(*this);
       }
       virtual void newCommonFunction() = 0;
       // 复杂逻辑,依赖Policy的一些策略方法
       //...
    };
    
    • 在每个派生类中实现这个虚函数。例如:
    template <typename T>
    class Derived1 : public CoreTemplate<T, Policy1> {
    public:
       void newCommonFunction() override {
          auto state = this->getRequiredState();
          // 基于Derived1的实现细节处理state
          //...
       }
    };
    
    template <typename T>
    class Derived2 : public CoreTemplate<T, Policy2> {
    public:
       void newCommonFunction() override {
          auto state = this->getRequiredState();
          // 基于Derived2的实现细节处理state
          //...
       }
    };
    
  2. 处理模板参数的类型兼容性
    • 模板参数推导:现代C++编译器支持模板参数的自动推导。例如,在创建派生类对象时,如果编译器能够根据上下文推导出模板参数类型,就可以简化代码。例如:
    Derived1<int> d1; // 明确指定模板参数
    auto d2 = std::make_unique<Derived2<double>>(); // 利用模板参数推导
    
    • 类型约束:可以使用C++20的概念(concepts)来约束模板参数的类型。例如,假设Policy需要满足某些特定的接口,可以定义一个概念:
    template <typename P>
    concept PolicyConcept = requires(P p) {
       { p.getState(std::declval<CoreTemplate<int, P>>()) } -> std::same_as<decltype(p.getState(std::declval<CoreTemplate<int, P>>()))>;
       // 其他所需的接口检查
    };
    template <typename T, PolicyConcept Policy>
    class CoreTemplate {
       //...
    };
    
  3. 编译期优化
    • 常量表达式和consteval:如果CoreTemplate中的某些逻辑在编译期就可以确定,可以使用constexpr函数或者C++20的consteval函数。例如,Policy中的一些策略方法如果在编译期就可以计算出结果,可以声明为constexprconsteval
    struct Policy1 {
       static constexpr auto getState(const CoreTemplate<int, Policy1>&) {
          return 42; // 假设这是一个编译期可计算的值
       }
    };
    
    • 模板特化:对于某些特定类型的模板参数,可以进行模板特化以优化性能。例如,如果Derived1在处理int类型时性能可以进一步优化,可以进行如下特化:
    template <>
    class Derived1<int> : public CoreTemplate<int, Policy1> {
    public:
       void newCommonFunction() override {
          auto state = this->getRequiredState();
          // 针对int类型的更优化实现
          //...
       }
    };