当继承的 类 都需要不同的成员时如何处理多重继承?
How to handle multiple inheritance when both inherited classes need a distinct member?
我有以下 类:
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 */};
};
我不能使用虚拟继承(我认为)因为 Major 和 Minor 需要分别控制一个舵机,不能相同。但是,当 Arm 完成移动时,它应该将 moving
成员设置为 false。当我输入 moving
.
时,Intellisense 显示 ServoPart::moving
moving
的这种访问会不会有歧义?如果是,我该如何解决?我关于虚拟继承的假设是否因为我有两个不同的伺服系统而无法使用它,对吗?
是的,它有歧义,编译器会报错。
你可以在Arm
的成员函数的代码中写Major::moving
或Minor::moving
来指定你想要的。
我怀疑你在这里是否有适当的“isa”关系。手臂不是马达。一个手臂 有 两个马达。您应该在这里使用组合而不是继承。请注意 Major
和 Minor
没有任何虚函数,因此没有理由更喜欢继承。
尝试:
class Arm {
Major major;
Minor minor;
void move() {
...
major.moving= false;
minor.moving= false;
...
现在如何引用组件就更明显了。但是对于(多重)继承,这是相同的想法。我还认为您引入名称 Major
和 Minor
只是为了绕过继承多个副本的限制。如果你使用组合,你可以避免:
class Arm {
ServoPart major;
ServoPart minor;
...
或者,因为它们现在是同一类型,也许可以改为创建一个数组。这使得向所有人“广播”相同的操作变得容易:
class Arm {
ServoPart joints[2];
void move() {
...
for (auto j : joints) j.moving= false;
更新
您的评论表明 ServoPart
具有虚拟 doJob
函数。您应该将其分离为一个没有数据成员的纯 接口 ,并从中派生出您的单电机 class。您的复合 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;
};
请注意,Arm
中 doJob
的实现可以为其包含的每个组件调用 doJob
,但它是一个单独的函数,不具有任何自动依赖他们。单个 Joint
和 Arm
实例都可以进行多态处理,因为它们具有公共接口。
我有以下 类:
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 */};
};
我不能使用虚拟继承(我认为)因为 Major 和 Minor 需要分别控制一个舵机,不能相同。但是,当 Arm 完成移动时,它应该将 moving
成员设置为 false。当我输入 moving
.
ServoPart::moving
moving
的这种访问会不会有歧义?如果是,我该如何解决?我关于虚拟继承的假设是否因为我有两个不同的伺服系统而无法使用它,对吗?
是的,它有歧义,编译器会报错。
你可以在Arm
的成员函数的代码中写Major::moving
或Minor::moving
来指定你想要的。
我怀疑你在这里是否有适当的“isa”关系。手臂不是马达。一个手臂 有 两个马达。您应该在这里使用组合而不是继承。请注意 Major
和 Minor
没有任何虚函数,因此没有理由更喜欢继承。
尝试:
class Arm {
Major major;
Minor minor;
void move() {
...
major.moving= false;
minor.moving= false;
...
现在如何引用组件就更明显了。但是对于(多重)继承,这是相同的想法。我还认为您引入名称 Major
和 Minor
只是为了绕过继承多个副本的限制。如果你使用组合,你可以避免:
class Arm {
ServoPart major;
ServoPart minor;
...
或者,因为它们现在是同一类型,也许可以改为创建一个数组。这使得向所有人“广播”相同的操作变得容易:
class Arm {
ServoPart joints[2];
void move() {
...
for (auto j : joints) j.moving= false;
更新
您的评论表明 ServoPart
具有虚拟 doJob
函数。您应该将其分离为一个没有数据成员的纯 接口 ,并从中派生出您的单电机 class。您的复合 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;
};
请注意,Arm
中 doJob
的实现可以为其包含的每个组件调用 doJob
,但它是一个单独的函数,不具有任何自动依赖他们。单个 Joint
和 Arm
实例都可以进行多态处理,因为它们具有公共接口。