Я хочу реализовать иерархию наследования в моей C++ игровой движок, который имеет некоторые аналогии с Java:Является ли множественное наследование от того же базового класса через разные родительские классы действительно проблемой?
- все объекты наследуют от класса
Object
, - некоторые функциональные возможности обеспечиваются интерфейсами.
Это просто аналогия, что дает мне некоторые преимущества (не является строгим 1: 1 Java: C++ отображения, которые не возможно).
Под «интерфейсом» я имею в виду здесь класс с чистыми виртуальными, общедоступными методами. Я знаю, что это не точное и точное определение.
Так что я сделал:
class Object{...};
/* interfaces */
class Nameable : public Object{...};
class Moveable : public Object{...};
class Moveable3D : public Moveable{...};
class Moveable2D : public Moveable{...};
class Model3D : public Moveable3D, public Nameable{...}
class Line3D : public Moveable3D{...}
class Level: public Nameable{...}
class PathSolver : public Object{...}
Как вы можете видеть, Model3D
Теперь наследуется от Object
через несколько способов:
Moveable3D -> Moveable -> Object
,Nameable -> Object
.
И мой компилятор в VS2013 (VC++) предупреждает меня об этом.
Это проблема?
Если да, то как решить проблему, чтобы получить лучшую структуру наследования?
Я думал о двух направлениях, но оба имеют больше недостатков, то преимущества:
- сбросив наследования между, например,
Nameable
иObject
. Но таким образомLevel
потерял бы свое наследство отObject
тоже (и мой первый гол был: все объекты наследуют отObject
класс). - Я также мог бы опустить
: public Object
с каждого интерфейса. Но таким образом я был бы вынужден вручную набирать:public Object
в каждом из многих финальных классов двигателей (Model3D
,Line3D
,Level
,PathSolver
). Таким образом, рефакторинг и создание новых конечных типов будут сложнее. Кроме того, информация о том, что каждый интерфейс будет гарантированно наследовать отObject
, теряется именно так.
Я хотел бы избежать виртуального наследования (один уровень абстракции дальнейшего) если это не нужно. Но может быть, это (по крайней мере, для : public Object
)?
@jxh Я не уверен, о чем вы просите. Но: любой 'Nameable' гарантированно будет' Object' (тот же для 'Moveable3D'). Но 'Moveable3D' не обязательно должен быть« Nameable »одновременно. Когда вы передаете 'Object *', вы не можете предположить, что это 'Nameable' или' Moveable3D', но вы можете, например. используйте 'dynamic_cast', чтобы проверить его. И, конечно, вы можете назначить любой другой тип «Object *» (это было бы лучше). ** Кроме того ** все интерфейсы имеют чистый виртуальный метод, поэтому вы не можете использовать их с помощью только 'new Nameable()', вам сначала нужно наследовать их. Это то, о чем вы просили? – PolGraphic
Ваша текущая структура означает, что 'Model3D' имеет два экземпляра' Object'. Таким образом, если вы попытаетесь присвоить ему ссылку «Object», вы получите ошибку неоднозначности, если вы не укажете, к какому «объекту» следует обращаться (один к «Nameable» или к «Moveable3D»). Но если вы используете виртуальное наследование, у вас будет только один объект «Object» («Nameable» и «Moveable3D» - тот же экземпляр «Object»). – jxh
Является ли 'Object' интерфейсом? – jxh