"Has a" C++ 中的关系,最好的做法是拥有一个 class "implement" 多个抽象基础 classes?
"Has a" relationships in C++, is it best practice to have a class "implement" multiple abstract base classes?
在Java中,您经常使用接口来表示class将具有特定的功能。
在 c++ 中,我知道这是通过抽象 classes 完成的,但是,我知道多重继承范式通常有一个长期存在的耻辱。
例如,假设您有需要在其上具有函数的游戏对象:
extends DealDamage 将有一个 DoDamage() 函数
extends TakeDamage 将有一个 TakeDamage() 函数
等等
你如何在 C++ 中最好地处理这个问题?
如果您想要的只是一种基于契约的 ("interface, extends") 设计方法,只需创建 classes 来定义您的实现 class 保证支持的接口。
例如:
class ITakeDamage {
virtual ~ITakeDamage() {} // virtual dtors for this design!
virtual void TakeDamage(const DamageMeasurement& hurtFactor) = 0; // ouch!
// ... some more stuff
};
class IDoDamage {
public:
virtual ~IDoDamage() {}
virtual void HurtSomething(ITakeDamage* recipient, DamageMeasurement hurtFactor) = 0; // take that!
// ... some more stuff
};
class NormalThingThatTakesAndGivesDamage : public ITakeDamage, public IDoDamage {
public:
NormalThingThatTakesAndGivesDamage();
~NormalThingThatTakesAndGivesDamage();
// etc...
// ITakeDamage interface members...
virtual void TakeDamage(const DamageMeasurement& hurtFactor) override;
// IDoDamage interface members...
virtual void HurtSomething(ITakeDamage* recipient, DamageMeasurement hurtFactor) override; // implement this
};
class IndestructibleThingThatHurtsOthers : public IDoDamage {
public:
IndestructibleThingThatHurtsOthers();
~IndestructibleThingThatHurtsOthers();
// etc...
// IDoDamage interface members...
virtual void HurtSomething(ITakeDamage* recipient, DamageMeasurement hurtFactor) override; // implement this
};
class HarmlessTarget : public ITakeDamage {
public:
HarmlessTarget();
~HarmlessTarget();
// etc...
// ITakeDamage interface members...
virtual void TakeDamage(const DamageMeasurement& hurtFactor) override; // implement this
};
正如 Sam 在他的评论中所说,多重继承是 C++ 中可用的更强大的功能之一。尽管我在这里使用纯虚拟接口作为示例(基于您问题的 "interface" 部分),但在某些情况下,继承多个基 class 也提供实现也是合适的。明智地使用和正确的设计,它甚至可以大大简化 class 之间的关系。使用不当,它会造成一团糟。任何 "stigma" 通常来自仅限于错误或不当使用的有限经验。
不要仅仅因为一种工具并不适用于所有情况,就把它从你的工具箱中拿出来。恕我直言,如果它能让您的架构更简单、更健壮且更易于维护,那就去做吧。
在Java中,您经常使用接口来表示class将具有特定的功能。
在 c++ 中,我知道这是通过抽象 classes 完成的,但是,我知道多重继承范式通常有一个长期存在的耻辱。
例如,假设您有需要在其上具有函数的游戏对象: extends DealDamage 将有一个 DoDamage() 函数 extends TakeDamage 将有一个 TakeDamage() 函数 等等 你如何在 C++ 中最好地处理这个问题?
如果您想要的只是一种基于契约的 ("interface, extends") 设计方法,只需创建 classes 来定义您的实现 class 保证支持的接口。
例如:
class ITakeDamage {
virtual ~ITakeDamage() {} // virtual dtors for this design!
virtual void TakeDamage(const DamageMeasurement& hurtFactor) = 0; // ouch!
// ... some more stuff
};
class IDoDamage {
public:
virtual ~IDoDamage() {}
virtual void HurtSomething(ITakeDamage* recipient, DamageMeasurement hurtFactor) = 0; // take that!
// ... some more stuff
};
class NormalThingThatTakesAndGivesDamage : public ITakeDamage, public IDoDamage {
public:
NormalThingThatTakesAndGivesDamage();
~NormalThingThatTakesAndGivesDamage();
// etc...
// ITakeDamage interface members...
virtual void TakeDamage(const DamageMeasurement& hurtFactor) override;
// IDoDamage interface members...
virtual void HurtSomething(ITakeDamage* recipient, DamageMeasurement hurtFactor) override; // implement this
};
class IndestructibleThingThatHurtsOthers : public IDoDamage {
public:
IndestructibleThingThatHurtsOthers();
~IndestructibleThingThatHurtsOthers();
// etc...
// IDoDamage interface members...
virtual void HurtSomething(ITakeDamage* recipient, DamageMeasurement hurtFactor) override; // implement this
};
class HarmlessTarget : public ITakeDamage {
public:
HarmlessTarget();
~HarmlessTarget();
// etc...
// ITakeDamage interface members...
virtual void TakeDamage(const DamageMeasurement& hurtFactor) override; // implement this
};
正如 Sam 在他的评论中所说,多重继承是 C++ 中可用的更强大的功能之一。尽管我在这里使用纯虚拟接口作为示例(基于您问题的 "interface" 部分),但在某些情况下,继承多个基 class 也提供实现也是合适的。明智地使用和正确的设计,它甚至可以大大简化 class 之间的关系。使用不当,它会造成一团糟。任何 "stigma" 通常来自仅限于错误或不当使用的有限经验。
不要仅仅因为一种工具并不适用于所有情况,就把它从你的工具箱中拿出来。恕我直言,如果它能让您的架构更简单、更健壮且更易于维护,那就去做吧。