c++ - 仅功能的多重继承 - 没有虚拟和 CRTP

标签 c++ c++14 multiple-inheritance crtp

如何仅仅为了功能做多重继承?

  • 必须共享基类的数据
  • 没有虚函数(假设 vtable 很昂贵)
  • 避免虚拟继承
  • 实现必须能够驻留在 .cpp 中
  • 允许使用 c++14

这里有类似的问题:-

这是一个示例代码(coliru demo):-

class O{
    protected: int database=0;  
};
class A : public O{
    public: void print(){
        std::cout<<database<<std::endl;
    }
};
class B : public O{
    public: void set(int s){
        database=s+1;
    }
};
class AB : public O{
    public: void print(){//duplicate
        std::cout<<database<<std::endl;
    }
    public: void set(int s){//duplicate
        database=s+1;
    }
};
//AB ab;  ab.set(1); ab.print(); // would print 2

这是我的尝试 ( wandbox demo )。我滥用 CRTP :( :-

class O{
    public: int database=0; 
};
template<class T>class OA{
    public: void print(){
        std::cout<<static_cast<T*>(this)->database<<std::endl;
    }
};
template<class T>class OB{
    public: void set(int s){
        static_cast<T*>(this)->database=s+1;
    }
};
class A :public O,public OA<A>{};
class B :public O,public OB<B>{};
class AB :public O,public OA<AB>,public OB<AB>{};

可以用,但看起来不够优雅。
此外,实现必须在 header 中(因为OAOB 是模板类)。

有更好的方法吗?或者这是要走的路吗?

对不起,如果这个问题太新手或已经问过。我是 C++ 初学者。

编辑

Give extended example of using please.

在 ECS 中,它在某些情况下很有用:-

class O{
    protected: EntityHandle e;  
};
class ViewAsPhysic : public O{                     //A
    public: void setTransform(Transformation t){
        Ptr<PhysicTransformComponent> g=e;
        g->transform=t;
    }
};
class ViewAsLight : public O{                      //B
    public: void setBrightness(int t){    
        Ptr<LightComponent> g=e;
        g->clan=t;
    }
};
class ViewAsLightBlock : public O{                 //AB
    //both functions 
};

最佳答案

这里的问题是 database 字段是类 O 的成员。因此如果没有虚拟继承,A 和 B 将各自拥有自己的 database 拷贝。所以你必须找到一种方法来强制 A 和 B 共享相同的值。例如,您可以使用在 protected 构造函数中初始化的引用字段:

#include <iostream>

class O{
    int _db;
    protected: int &database;
    O(): database(_db) {};
    O(int &db): database(db) {};
};
class A : public O{
    public: void print(){
        std::cout<<database<<std::endl;
    }
    A() {}                                // public default ctor
    protected: A(int& db): O(db) {};      // protectect ctor
};
class B : public O{
    public: void set(int s){
        database=s+1;
    }
    B() {}                                // public default ctor
    protected: B(int& db): O(db) {};      // protectect ctor
};
class AB : public A, public B {
    int _db2;
    public: AB(): A(_db2), B(_db2) {};    // initialize both references to same private var
};

int main() {
    AB ab;
    ab.set(1);
    ab.print();
    return 0;
}

按预期显示:

2

以上代码没有使用虚继承,没有虚函数,也没有模板,所以方法可以安全地在cpp文件中实现。 AB 类实际上使用了其父类的方法,并且对其基础数据仍然有一个连贯的 View 。事实上,它通过在最派生类中构建公共(public)数据并通过其父类中的 protected 构造函数注入(inject)来模拟显式虚拟继承。

关于c++ - 仅功能的多重继承 - 没有虚拟和 CRTP,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45412092/

相关文章:

c++ - 没有与 lambda 匹配的函数 std::forward

perl - 为什么这个方案会出现错误 "Inconsistent hierarchy during C3 merge"?

c++ - 将对象转换为其基数的子集

c++ - 如何将 cpp 文件添加到 Visual Studio 2008?

c++ - 初始化结构中的常量数组

c++ - boost::asio 取消或关闭在 async_handle 上不起作用

c++ - C++中多重继承的限制

c++ - 保留一个潜在的文件句柄

c++ - 将整个文件读入线 vector 的最有效方法

c++ - 用于收集可调用对象的 std::function 的替代方法