将继承重构为模板,同时保留某些特征

Refactoring inheritance into templates while retaining certain characteristics

本文关键字:保留 特征 重构 继承      更新时间:2023-10-16

我有以下结构:

class Base {
   virtual T foo() = 0;
};
class Derived : public Base {
   T foo() override { /**/ }
}
class Derived1 : public Base {
   T foo() override { /**/ }
}

我需要以下内容才能工作(或适当的替代品):

some_container<unique_ptr<Base>> objects;

基本上
C++ AMP 不允许内核中的虚拟函数,但我绝对需要类似继承链的容器行为。

这种继承链转换为模板魔术的推荐/通用模式是什么?

删除 vtable 调用的规范方法是将其替换为 switch 语句:

enum type_e
{
   type_derived,
   type_derived1
};
class Base
{
public:
   Base( type_e type ) : m_type( type ) {}
   T foo();
private:
   type_e m_type;
};

T Base::Foo()
{
   switch( m_type )
   {
   case type_derived:
      return //{...} your Derived::Foo()
   case type_derived1:
      return //{...} your Derived1::Foo()
   }
}

API 中唯一的变化是,您必须调用new Base( type_derived )而不是调用new Derived()。主要缺点是你现在必须将所有额外的数据(以前是Derived1或Derived的成员)保存在Base中,这可能会使类膨胀。另一方面,您现在可以按值制作 Base 的容器,并避免 std::unique_ptr 的开销。

您可以推出自己的手动 vtable 仿真:

class Base {
protected:
    using fp_t = int(*)(Base*);
    fp_t fp;
    Base( fp_t p ) : fp( p ) {}     
public:
    int foo() { return (*fp)(this); }
};
class Derived : public Base {
    static int sfoo(Base* b) { return static_cast<Derived*>(b)->foo(); }
    int foo() { return 42; }
public:
    Derived() : Base(&sfoo) {}
};

现场示例