简体   繁体   English

当两个继承的类都需要不同的成员时,如何处理多个 inheritance?

[英]How to handle multiple inheritance when both inherited classes need a distinct member?

I have the following classes:我有以下课程:

class ServoPart {
protected:
    virtual void doJob(byte* job) = 0;

private:
    bool moving;
    Servo servo;
};

// the following classes only have a constructor so I can use two ServoParts to inherit from
class Major: public ServoPart {};
class Minor: public ServoPart {};

class Arm: public Major, public Minor {
private:
    void move() {
        // do stuff
        if (target == current) {
            moving = false;
        }
    };

public:
    void doJob(byte* job) {/* do stuff */};
};

I can't use virtual inheritance (I think) because the Major and Minor need to control one servo each which can't be the same.我不能使用虚拟 inheritance(我认为),因为 Major 和 Minor 需要分别控制一个不能相同的伺服。 However, when the Arm is done moving, it should set the moving member to false.但是,当 Arm 完成移动时,应将moving构件设置为 false。 Intellisense shows ServoPart::moving , when im typing moving .当我输入移动时,智能感知显示ServoPart::moving moving

Would this access of moving be ambiguous?这种moving的访问方式会模棱两可吗? If yes, how can I fix this?如果是,我该如何解决这个问题? Is my assumption about virtual inheritance, that I can't use it because I have two different servos, correct?我对虚拟 inheritance 的假设是因为我有两个不同的伺服系统,所以我不能使用它,对吗?

Yes, it is ambiguous and the compiler will complain.是的,它是模棱两可的,编译器会抱怨。 You can write Major::moving or Minor::moving within the code of Arm 's member functions to specify which you want.您可以在Arm的成员函数的代码中编写Major::movingMinor::moving来指定您想要的。

I question whether you have a proper "isa" relationship here.我怀疑你在这里是否有适当的“isa”关系。 An arm is not a motor. arm 不是电机。 An arm has two motors. arm两个电机。 You should be using composition here instead of inheritance.您应该在这里使用合成而不是 inheritance。 Note that Major and Minor don't have any virtual functions so there is no reason to prefer inheritance.请注意, MajorMinor没有任何虚拟功能,因此没有理由更喜欢 inheritance。

Try:尝试:

class Arm {
   Major major;
   Minor minor;
   void move() {
     ...
     major.moving= false;
     minor.moving= false;
     ...

It is more obvious now how to refer to the components.现在如何引用组件更加明显。 But with (multiple) inheritance it is the same idea.但是对于(多个)inheritance 是相同的想法。 I think also you are introducing the names Major and Minor just to get around the limit of inheriting more than one copy.我认为您还引入名称MajorMinor只是为了绕过继承多个副本的限制。 If you used composition, you can avoid that:如果您使用合成,则可以避免:

class Arm {
   ServoPart major;
   ServoPart minor;
...

Or, since they are the same type now, perhaps make an array instead.或者,由于它们现在是相同的类型,也许可以创建一个数组。 This makes it easy to "broadcast" the same operation to all of them:这使得向所有人“广播”相同的操作变得容易:

class Arm {
    ServoPart joints[2];
    void move() {
        ...
        for (auto j : joints)  j.moving= false;

update更新

Your comment indicates ServoPart has a virtual doJob function.您的评论表明ServoPart有一个虚拟doJob function。 You should separate that into a pure interface that has no data members, and derive your single-motor class from that.您应该将其分离为没有数据成员的纯接口,并从中派生出您的单电机 class。 Your composited class can also inherit from that interface.您的复合 class 也可以从该接口继承。

struct Servo_Interface {
    virtual void doJob() =0;
};

class Joint : Servo_Interface {
    bool moving;
    Servo servo;
public:
    void doJob()  override;
};

class Arm : Servo_Interface {
    Joint joints[2];
public:
    void doJob()  override;
};

Note that the implementation of doJob in Arm can call doJob for each of the components it contains, but it is a separate function that does not have any automatic reliance on them.请注意, doJob中的Arm的实现可以为其包含的每个组件调用doJob ,但它是一个单独的 function,不会自动依赖它们。 Both single Joint and Arm instances can be treated polymorphically since they have a common interface.单个JointArm实例都可以进行多态处理,因为它们具有通用接口。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM