You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

利用C++模板与Concept实现无继承的类专属func方法

用模板与Concept实现无继承的代码复用(共享proc逻辑+专属func)

问题背景

现有C++代码中,Derived类继承Base类后,调用Derived的proc方法时,执行的是Base类的func,达不到预期的Derived::func输出。需求是:让多个类共享proc里的大量公共代码,同时每个类拥有专属的func方法,完全不使用继承,能否通过模板与Concept编程实现?

原代码

// templateInheritance.cpp

#include <iostream>

template <typename T>
class Base{
public:
    void func(){                    // (1)
        std::cout << "Base::func\n";
    }

    void proc()
    {
        // huge stuff goes here
        func();
        // huge stuff goes here
    }
};

template <typename T>
class Derived: public Base<T>{
public:
    void func(){                    // (2)
        std::cout << "Derived::func\n";
    }
};

int main(){

    std::cout << '\n';

    Derived<int> derived;
    derived.proc();
    Base<int> base;
    base.proc();            

    std::cout << '\n';

}

预期输出

Derived::func
Base::func

解决方案:模板+Concept实现无继承复用

完全可以实现,核心思路是将共享的proc逻辑抽离为模板函数(或模板类),用Concept约束类型必须具备func方法,从而实现编译期的类型检查与代码复用,同时避免继承带来的问题。

方案1:模板自由函数+Concept(推荐)

这种方式最简洁,直接把共享逻辑做成独立的模板函数,只要类满足Concept要求就能调用:

#include <iostream>
#include <concepts>

// 定义Concept:要求类型必须有可调用的void func()方法
template<typename T>
concept HasFunc = requires(T t) {
    { t.func() } -> std::same_as<void>;
};

// 共享的proc逻辑,作为模板函数
template<HasFunc T>
void proc(T& obj) {
    // 这里放置所有公共代码
    obj.func(); // 直接调用对象的专属func
    // 这里放置所有公共代码
}

// 自定义Base类,自带专属func
class Base {
public:
    void func() {
        std::cout << "Base::func\n";
    }
};

// 自定义Derived类,自带专属func
class Derived {
public:
    void func() {
        std::cout << "Derived::func\n";
    }
};

int main() {
    std::cout << '\n';

    Derived derived;
    proc(derived); // 调用Derived::func
    Base base;
    proc(base);    // 调用Base::func

    std::cout << '\n';
}

方案说明

  • ConceptHasFunc在编译期检查传入的类型是否具备void func()方法,不符合的类型会直接触发编译错误,提前发现问题。
  • proc作为独立模板函数,所有符合要求的类都能直接调用,完全不需要继承关系。
  • 每个类的func都是自身的专属实现,proc会直接调用对应对象的func,完美匹配预期输出。

方案2:组合式模板类+Concept

如果需要将共享逻辑封装成类(比如需要持有状态),可以用组合代替继承,把自定义类作为模板类的成员:

#include <iostream>
#include <concepts>
#include <utility>

// 同样用Concept约束类型
template<typename T>
concept HasFunc = requires(T t) {
    { t.func() } -> std::same_as<void>;
};

// 封装共享逻辑的模板类,持有自定义类型对象
template<HasFunc T>
class ProcHolder {
private:
    T obj_;
public:
    // 转发构造函数,支持自定义类的任意构造方式
    template<typename... Args>
    ProcHolder(Args&&... args) : obj_(std::forward<Args>(args)...) {}

    void proc() {
        // 大量公共代码
        obj_.func();
        // 大量公共代码
    }

    // 暴露底层对象(如果需要调用自定义类的其他方法)
    T& get_obj() { return obj_; }
    const T& get_obj() const { return obj_; }
};

class Base {
public:
    void func() {
        std::cout << "Base::func\n";
    }
};

class Derived {
public:
    void func() {
        std::cout << "Derived::func\n";
    }
};

int main() {
    std::cout << '\n';

    ProcHolder<Derived> derived;
    derived.proc();
    ProcHolder<Base> base;
    base.proc();

    std::cout << '\n';
}

方案说明

  • 通过组合的方式将自定义类对象嵌入ProcHolder,避免了继承的耦合。
  • 同样依靠Concept确保传入的类型具备func方法,编译期检查类型合法性。
  • 适合需要在共享逻辑中持有状态,或者需要封装更多接口的场景。

为什么原代码失效?

原代码中Base的proc调用的是自身的func,因为func不是虚函数,Derived的func只是隐藏了Base的同名方法,而非多态覆盖。因此调用derived.proc()时,实际执行的是Base<T>::proc,自然会调用Base<T>::func。

内容的提问来源于stack exchange,提问作者Ted Zach

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 01:35:37