У меня есть класс Parent
и два класса Child
:
class Parent
{
};
class Child1: public Parent
{
};
class Child2 : public Parent
{
};
Я хотел бы вторую иерархию классов с классом Cousin
наверху иерархии и подклассами, называемыми Cousin1
, Cousin2
и т. д.:
class Cousin
{
virtual void doUsefulWork() = 0;
};
class Cousin1 : public Cousin
{
virtual void doUsefulWork() override
{
// One behaviour
}
};
class Cousin2 : public Cousin
{
virtual void doUsefulWork() override
{
// A different behaviour
}
};
Каждый подкласс Child
ДОЛЖЕН наследовать подкласс Cousin
, чтобы иметь реализацию doUsefulWork()
:
class Child1 : public Parent, Cousin1
{
// Has implementation of doUsefulWork() from Cousin1
};
Как защититься от того, чтобы автор подкласса Child
забыл наследовать подкласс Cousin
? Мне нужно что-то, что вызывает ошибку времени компиляции.
Каждый подкласс Child
должен иметь доступ к реализации doUsefulWork()
.
Я думал о том, чтобы Cousin
наследовать от Parent и определить чистый виртуальный doUsefulWork()
в Parent
, но тогда у меня возникнут сложные проблемы с множественным наследованием в подклассах Child
?
Parent
отCousin
. Это по крайней мере вызовет ошибку компиляции, если автор классаChild
забудет повторно реализоватьdoUsefulWork()
или наследовать от класса, который имеет реализацию. - person dave   schedule 28.11.2018class Parent : public Cousin { ...
поможет. - person Eljay   schedule 28.11.2018struct Child : Parent
на самом деле означает, что каждыйChild
является-aParent
, неудивительно, что это вызывает путаницу, когда ОО понимается так - person 463035818_is_not_a_number   schedule 28.11.2018class Parent: public Cousin {
такая уж хорошая идея. Получениеclass Child1: public Parent, Cousin1 {
будет иметь базовый классCousin
дважды (и это пахнет необходимостью виртуального наследования...) - person Scheff's Cat   schedule 28.11.2018Child1
доступ с помощью указателя наParent
делает виртуальный методdoUsefulWork()
невидимым. Это указатель наCousin
, который необходим. Если, в свою очередь,Child3
случайно не является производным от какого-либоCousinX
с переопределеннымdoUsefulWork()
, назначение его указателю наCousin
должно вызвать проблемы. Есть что-то тонкое, о чем я еще не знаю. - person Scheff's Cat   schedule 28.11.2018Cousin
? В любом случае ассоциация была бы намного чище. Если вам нужно получить доступ к защищенным членамCousin
, как насчет того, чтобы сделать ихfriend
s? - person Detonar   schedule 28.11.2018Cousin1
должен обеспечить реализацию путем переопределения.Cousin
как раз наводит на это нужду (по чистой виртуалке). (как я понял) - person Scheff's Cat   schedule 28.11.2018doUsefulWork()
указатель объекта должен иметь типCousin*
(неParent*
). Назначение указателяChildX
наCousin*
вызовет жалобы компилятора, если нет наследования от какого-либо производногоCousinX
. На самом деле, я скорее вижу опасность, чтоChildX
правильно получено изCousinX
, но не изParent
. - person Scheff's Cat   schedule 28.11.2018void doUsefulWork()
. Что мне говоритParent: public Cousin
. - person jlanik   schedule 28.11.2018ChildX
. Эта информация, вероятно, будет полезна, чтобы прояснить это. - person Scheff's Cat   schedule 28.11.2018