mat*_*tor 1 c++ multiple-inheritance virtual-inheritance ambiguous
我有以下课程:
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 */};
};
Run Code Online (Sandbox Code Playgroud)
我不能使用虚拟继承(我认为),因为 Major 和 Minor 需要分别控制一个不能相同的伺服器。但是,当 Arm 完成移动时,它应该将moving成员设置为 false。Intellisense 显示ServoPart::moving,当我打字时moving。
这种访问moving会模棱两可吗?如果是,我该如何解决这个问题?我对虚拟继承的假设是我不能使用它,因为我有两个不同的伺服器,对吗?
是的,这是模棱两可的,编译器会抱怨。您可以编写Major::moving或Minor::moving在Arm的成员函数的代码中指定您想要的。
我怀疑你在这里是否有适当的“isa”关系。手臂不是马达。一个手臂有两个电机。您应该在这里使用组合而不是继承。请注意,Major并且Minor没有任何虚函数,因此没有理由更喜欢继承。
尝试:
class Arm {
Major major;
Minor minor;
void move() {
...
major.moving= false;
minor.moving= false;
...
Run Code Online (Sandbox Code Playgroud)
现在更清楚如何引用组件了。但是对于(多重)继承,它是相同的想法。我认为您也在引入名称Major,Minor只是为了绕过继承多个副本的限制。如果您使用组合,则可以避免这种情况:
class Arm {
ServoPart major;
ServoPart minor;
...
Run Code Online (Sandbox Code Playgroud)
或者,由于它们现在是相同的类型,也许可以创建一个数组。这使得向所有人“广播”相同的操作变得容易:
class Arm {
ServoPart joints[2];
void move() {
...
for (auto j : joints) j.moving= false;
Run Code Online (Sandbox Code Playgroud)
您的评论表明ServoPart具有虚拟doJob功能。您应该将其分离为一个没有数据成员的纯接口,并从中派生出您的单电机类。您的复合类也可以从该接口继承。
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;
};
Run Code Online (Sandbox Code Playgroud)
请注意,doJobin的实现Arm可以调用doJob它包含的每个组件,但它是一个单独的函数,不会自动依赖它们。单个Joint和Arm实例都可以多态处理,因为它们有一个公共接口。