给定基类方法的编译时覆盖

Posted

技术标签:

【中文标题】给定基类方法的编译时覆盖【英文标题】:Compile-time override of given base class methods 【发布时间】:2019-11-21 00:45:34 【问题描述】:

是否可以在派生模板类中为参数化基类型有条件地覆盖基方法? 我的意思是,我有不同的基类,其中包含它们的默认方法定义,我想在编译时定义,我想使用哪个基类以及我想覆盖该类中的哪些方法,传递类似 lambda 函数的东西,这将在重写的实现中被调用。喜欢:

struct BaseOne

    virtual void f(int& x, const int& y)
    
        x += y;
    
;

struct BaseTwo

    virtual void g(double& x)
    
        x += 1.0;
    
;

template<class BaseT/*, method m signature and ID, CallbackT callback*/>
struct Derived: public BaseT

    /* <mID>(mSignature)> = override
    
        callback(<mSignatureArgs...>);
    
    */
    // Such that here I do not have to define all methods from BaseT, that could potentially be requested to be overridden at compile-time
;

int main()

    Derived<BaseOne> d1; // default BaseOne::f definition
    Derived<BaseTwo, /* method g, [](double& x)  x += 2;  */> d2; // overridden BaseTwo::g definition

编辑: BaseOneBaseTwo接口是由外部工具生成的,它们的接口不能改变,即它们的接口方法是多态的,不能依赖于派生类中的特定实现,必须具有相同的公共基类类型(基类中没有模板) 和BaseOne 的所有派生词都与常规多态性一样使用:

void doSomethingWithOnes(BaseOne& one)

    int x = /* get some x */;
    int y = /* get some y */;
    one.g(x, y); // this call must be virtual
    /* use x and y somehow */

【问题讨论】:

也许使用std::enable_if_v 或类似方法在两个不同的Derived 类之间进行选择,每个类都继承自两个不同的基类? 很好的问题,你知道 CRTP 吗? @Superlokkus ,有趣,以前没听说过,但刚刚读过。 AFAIU,CRTP 在这里不适用,因为在 CRTP 中基类不同,例如如果我有template&lt;class DerivedT&gt; struct BaseOne 模板和两个不同的实例化BaseOne&lt;Derived1&gt;BaseOne&lt;Derived2&gt;,那么这两个实例化将是没有公共基类的不同类类型。但在我的情况下,Base* 类必须保持虚拟接口。实际上,我无法更改基类,因为它们是由外部工具生成的。 我理解你的意思吗:你不能改变基类?你想用那些派生类实现什么,你想如何使用它们?请将其添加到您的问题中。 是否可以将BaseTwo::g 重命名为f 【参考方案1】:

将这些实现为本地类会容易得多:

int main()

    class : BaseOne
    
        // default BaseOne::f definition
     d1;

    class : BaseTwo
    
        // overridden BaseTwo::g definition
        void g(double& x) override
        
            x += 2;
        
     d2;

这些可以使用 lambda 可以使用的完全相同的东西,并且更清晰,同时仍然在它们的使用位置附近定义。

【讨论】:

优雅,完全忘记了本地类的存在

以上是关于给定基类方法的编译时覆盖的主要内容,如果未能解决你的问题,请参考以下文章

多态实现的机制

virtual虚函数

C#中具有相同名称和签名但返回类型不同的方法

限制指针类型模板参数和覆盖模板基类的虚拟方法

Visual Studio 2008 在编译模板时不关心基类的存在?

为啥当我有两个函数时编译器没有显示错误,一个将基类作为参数,一个将派生类作为参数?