C ++: приведение к интерфейсу, который не является частью базового класса - PullRequest
4 голосов
/ 13 июля 2010

У меня есть серия классов, представляющих «умные» элементы карты: MapTextElement, MapIconElement и т. Д. Классы расширяют различные классы графических элементов Qt, но также предоставляют общие функциональные возможности, такие как метод абстрактной фабрики, который возвращает панель свойств, предназначенная для каждого класса. Я объявил эти распространенные методы в чисто виртуальном классе MapElementInterface. Мои классы затем наследуют соответствующий базовый класс Qt, а также интерфейс:

class MapTextElement : public QGraphicsTextItem, public MapElementInterface
class MapIconElement : public QGraphicsItem, public MapElementInterface

Итак, моя иерархия классов выглядит примерно так:

         +-------------+    +-------------------+
         |QGraphicsItem|    |MapElementInterface|
         +-------------+    +-------------------+
                ^                   ^   ^
                |                   |   |
         +------+------+            |   |    
         |             |            |   |
+-----------------+   +--------------+  |
|QGraphicsTextItem|   |MapIconElement|  |
+-----------------+   +--------------+  |
     ^                                  |
     |                                  |
     +-------------------+        +-----+
                         |        |
                      +--------------+
                      |MapTextElement|
                      +--------------+

Я получаю указатель на QGraphicsItem из метода, предоставленного Qt. В этом случае я знаю , что указатель не только QGraphicsItem, но также MapElementInterface. Я хочу трактовать указатель как MapElementInterface.

QList<QGraphicsItem*> selected = scene_->selectedItems();
if (selected.count() == 1) {
  // We know that the selected item implements MapEditorInterface
  MapElementInterface *element = SOME_CAST_HERE<MapElementInterface*>(selected[0]);
  QWidget *panel = element->GeneratePropertyPanel(property_dock_);
}

Какой правильный состав использовать? Или я поступаю совершенно неправильно?

Ответы [ 4 ]

3 голосов
/ 13 июля 2010

При множественном наследовании dynamic_cast является единственным способом и проверяет возвращаемое значение на NULL.

3 голосов
/ 13 июля 2010

Кто-то опубликовал здесь хорошее объяснение.

Когда следует использовать static_cast, dynamic_cast, const_cast и reinterpret_cast?

2 голосов
/ 13 июля 2010

Вы должны быть осторожны, потому что, учитывая диаграмму, ваш указатель может указывать либо на MapTextElement, либо на MapIconElement. Единственная надежная ставка для вас - это использовать динамический кастинг. Или предоставьте другой способ определить тип объекта.

1 голос
/ 13 июля 2010

Вы можете привести к MapIconElement, а затем к MapElementInterface, или вы можете привести к MapTextElement, затем к MapElementInterface. Вы должны выбрать путь (или динамическое приведение вниз, чтобы проверить, какой путь вы выберете).

...