"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" 通常来自仅限于错误或不当使用的有限经验。

不要仅仅因为一种工具并不适用于所有情况,就把它从你的工具箱中拿出来。恕我直言,如果它能让您的架构更简单、更健壮且更易于维护,那就去做吧。