【问题标题】:Refactoring inheritance into templates while retaining certain characteristics将继承重构为模板,同时保留某些特征
【发布时间】:2013-10-26 08:03:51
【问题描述】:

我有以下结构:

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 不允许在内核中使用虚函数,但我肯定需要类似继承链的容器行为。

将这种继承链转换为模板魔法的推荐/常见模式是什么?

【问题讨论】:

标签: c++ c++11


【解决方案1】:

删除 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 的开销。

【讨论】:

    【解决方案2】:

    您可以滚动自己的手动 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) {}
    };
    

    Live example

    【讨论】:

    • 是的,这看起来很正常。我实际上不知道 CUDA 的问题是什么;就目前而言,您仍然需要在设备内存中进行动态分配,我认为这是困难的部分。
    • @KerrekSB 看起来 GPU 上的函数调用通常存在问题,因为没有堆栈的概念。似乎所有内容都是严格内联的,并且在并非不可能的情况下对调用进行去虚拟化是很困难的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-12-21
    • 2021-08-09
    • 1970-01-01
    • 2013-06-08
    • 2020-11-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多