Доступ к дочернему классу в массиве базового класса

#c #polymorphism #smart-pointers #rtti

Вопрос:

У меня есть массив базовых классов, элементы которого содержат дочерний класс. Проблема в том, что когда я пытаюсь получить доступ к дочернему классу в массиве, я получаю ошибку no operator "[]" matches these operands при попытке сделать:

 shared_ptr<P>amp; tmpP= (*arrayOfC)[(int)x][(int)y];
 

Я пытаюсь получить доступ к дочернему классу. Если я это сделаю:

 arrayOfC[(int)x][(int)y]
 

тогда я смогу получить доступ к базовому классу, который мне не нужен.
Я пытался использовать dynamic_cast безрезультатно.

Массив является

 shared_ptr<C> arrayOfC[800][600];
 

Это объявлено в другом заголовочном файле и также использует прямое объявление.
Вот как его спасают:

 shared_ptr<P> childClassP= make_shared<P>(z, x, y);
arrayOfC[(int)x][(int)y] = std::move(childClassP);
 

Комментарии:

1. std::dynamic_pointer_cast ? — cplusplus.com/reference/memory/dynamic_pointer_cast

2. Я пробовал это, но где бы я это использовал, я думаю, что использовал это неправильно.

3. auto tmpC_derived = std::dynamic_pointer_cast<C_derived>(arrayOfC_base[x][y]); должен это сделать.

4. Является ли C базовым классом или дочерним классом?

5. C — базовый класс, есть два дочерних класса.

Ответ №1:

Вам нужно использовать std::dynamic_pointer_cast , плюс, вам также нужно иметь, по крайней мере, виртуальный деструктор в базовом классе, чтобы генерировать виртуальные таблицы, чтобы сделать классы полиморфно связанными.

 #include <memory>

struct C {
    virtual ~C() {}
};

struct P : public C {

};

std::shared_ptr<C> arrayOfC[8][6];

int main() {
    auto derived_ptr = std::make_shared<P>();
    int x {2};
    int y {2};
    arrayOfC[x][y] = std::move(derived_ptr);

    // does not compile: std::shared_ptr<P> view = arrayOfC[x][y];

    std::shared_ptr<P> view = std::dynamic_pointer_cast<P>(arrayOfC[x][y]);

    return 0;
}
 

Видишь http://www.cplusplus.com/reference/memory/dynamic_pointer_cast/

Демо: https://godbolt.org/z/qn9oq4zfb