从 C++ 中的两个兄弟继承的最佳风格是什么?
What's the best style of Inheriting from two brothers in C++?
我需要实现几个模块,如下所示,
#include <stdio.h>
class Base{
protected:
int data;
};
class ModeA : public Base{};
class ModeB : public Base{};
class ModeHybrid: public ModeA, public ModeB{
public:
void func(){printf("%d\n", this->data);}
};
int main(){
ModeHybrid mh;
mh.func();
}
其中,
- 有个class'Base'
- 两个模块'ModeA'和'ModeB'继承自'Base'
- 混合模块 'ModeHybrid' 继承自 'ModeA' 和 'ModeB'
但是,成员变量 'data' 将被复制,因为 'ModeHybrid' 继承自 'ModeA' 和 'ModeB'。
有什么办法可以避免这种情况吗?
这是多重继承中的菱形问题。解决方案是使用 virtual
class ModeA : virtual public Base{};
class ModeB : virtual public Base{};
至少有三种方法可以解决这个问题。
首先是virtual
继承,有开销。其中,你只有一个Base
.
class ModeA : public virtual Base{};
class ModeB : public virtual Base{};
它确实意味着你实例化的最派生class必须构造Base
。
另一种方法是基于模板的,您传入 class 您希望父项派生自的
class Base{
protected:
int data;
};
template<class B=Base>
class ModeA : public B{};
template<class B=Base>
class ModeB : public B{};
class ModeHybrid:
public ModeA<ModeB<Base>>
{
public:
void func(){printf("%d\n", this->data);}
};
另一种方法是将数据填充到其他地方,并使 Base
成为具有 getData()
方法的抽象接口。
class Base{
protected:
int readData() const = 0;
int& writeData() = 0;
};
class ModeA : public Base{};
class ModeB : public Base{};
class ModeHybrid:
public ModeA, public ModeB
{
public:
void func(){printf("%d\n", this->readData());}
};
template<class X>
struct ImplementBase:X {
int data;
int readData() const final { return data; }
int& writeData() final { return data; }
};
ImplementBase<ModeHybrid> hybrid;
此版本在其层次结构中有两个 Base
class,但我们并不关心。数据存在于 ImplementBase
.
我需要实现几个模块,如下所示,
#include <stdio.h>
class Base{
protected:
int data;
};
class ModeA : public Base{};
class ModeB : public Base{};
class ModeHybrid: public ModeA, public ModeB{
public:
void func(){printf("%d\n", this->data);}
};
int main(){
ModeHybrid mh;
mh.func();
}
其中,
- 有个class'Base'
- 两个模块'ModeA'和'ModeB'继承自'Base'
- 混合模块 'ModeHybrid' 继承自 'ModeA' 和 'ModeB'
但是,成员变量 'data' 将被复制,因为 'ModeHybrid' 继承自 'ModeA' 和 'ModeB'。
有什么办法可以避免这种情况吗?
这是多重继承中的菱形问题。解决方案是使用 virtual
class ModeA : virtual public Base{};
class ModeB : virtual public Base{};
至少有三种方法可以解决这个问题。
首先是virtual
继承,有开销。其中,你只有一个Base
.
class ModeA : public virtual Base{};
class ModeB : public virtual Base{};
它确实意味着你实例化的最派生class必须构造Base
。
另一种方法是基于模板的,您传入 class 您希望父项派生自的
class Base{
protected:
int data;
};
template<class B=Base>
class ModeA : public B{};
template<class B=Base>
class ModeB : public B{};
class ModeHybrid:
public ModeA<ModeB<Base>>
{
public:
void func(){printf("%d\n", this->data);}
};
另一种方法是将数据填充到其他地方,并使 Base
成为具有 getData()
方法的抽象接口。
class Base{
protected:
int readData() const = 0;
int& writeData() = 0;
};
class ModeA : public Base{};
class ModeB : public Base{};
class ModeHybrid:
public ModeA, public ModeB
{
public:
void func(){printf("%d\n", this->readData());}
};
template<class X>
struct ImplementBase:X {
int data;
int readData() const final { return data; }
int& writeData() final { return data; }
};
ImplementBase<ModeHybrid> hybrid;
此版本在其层次结构中有两个 Base
class,但我们并不关心。数据存在于 ImplementBase
.