给定基类方法的编译时覆盖
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
编辑:
BaseOne
和BaseTwo
接口是由外部工具生成的,它们的接口不能改变,即它们的接口方法是多态的,不能依赖于派生类中的特定实现,必须具有相同的公共基类类型(基类中没有模板) 和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<class DerivedT> struct BaseOne
模板和两个不同的实例化BaseOne<Derived1>
和BaseOne<Derived2>
,那么这两个实例化将是没有公共基类的不同类类型。但在我的情况下,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 可以使用的完全相同的东西,并且更清晰,同时仍然在它们的使用位置附近定义。
【讨论】:
优雅,完全忘记了本地类的存在以上是关于给定基类方法的编译时覆盖的主要内容,如果未能解决你的问题,请参考以下文章