Компилятор помечает ситуацию такого типа (т. Е. Пытается вызвать (some instance of RoboticsEngineer).buildRobot()
) как ошибку.
Это происходит потому, что производный объект получил копию обоих базовых объектов (a MechanicalEngineer
экземпляр и ElectricalEngineer
экземпляр) внутри себя и одной только сигнатуры метода недостаточно, чтобы указать, какой из них использовать.
Если вы переопределите buildRobot
в своем RoboticsEngineer
, вы сможете сказатьявно какой унаследованный метод использовать с префиксом имени класса, например:
void RoboticsEngineer::buildRobot() {
ElectricalEngineer::buildRobot()
}
Одной и той же монетой можно фактически «заставить» компилятор использовать ту или иную версию buildRobot
, добавив к ней префиксимя класса:
(some instance of RoboticsEngineer).ElectricalEngineer::buildRobot();
в этом случае будет вызвана реализация метода ElectricalEngineer
, без двусмысленности.
Особый случай дается, когда у вас есть база Engineer
присвойте MechanicalEngineer
и ElectricalEngineer
, и вы укажете наследование virtual
в обоих случаях.Когда используется virtual
, производный объект не содержит двух экземпляров Engineer
, но компилятор обеспечивает наличие только одного из них.Это будет выглядеть так:
class Engineer {
void buildRobot();
};
class MechanicalEngineer: public virtual Engineer {
};
class ElectricalEngineer: public virtual Engineer {
};
В этом случае
(some instance of RoboticsEngineer).buildRobot();
будет разрешено без двусмысленностей.То же самое верно, если buildRobot объявлен virtual
и переопределен в одном из двух производных классов.В любом случае, если оба производных класса (ElectricalEngineer и MechanicalEngineer) переопределяют buildRobot
, тогда возникает неоднозначность, и компилятор помечает попытку вызова (some instance of RoboticsEngineer).buildRobot();
как ошибку.