Вектор указателей на базовый класс, содержащий объекты базового и производного классов - доступ к переменным производного класса c - PullRequest
0 голосов
/ 14 апреля 2020

Я боролся с этим C ++ некоторое время. Я создал базовый класс объектов и класс производных объектов, и я пытаюсь сохранить ссылки как на базовые, так и на производные объекты в векторе указателей базового класса (избегайте нарезки объектов). С помощью указателя я могу запускать виртуальные методы и могу подтвердить, что указатель указывает на объект производного класса, однако я не могу добраться до переменных производного класса c. Есть ли способ сделать это?

Объект базового класса:

class Base
{

public:

    Manager* manager;

    Base(){}
    Base(Manager* mManager){
        manager = mManager;
    }

    virtual void init(){}

    virtual void speak() {
        std::cout << "Base class is speaking!" << std::endl;
    }

};

Объект производного класса:

class Derived : public Base
{

public:

    Manager* manager;

    int DerviedVariable = 100;

    Derived(){}
    Derived(Manager* mManager){
        manager = mManager;
    }

    void speak() override {
        std::cout << "Derived class is speaking!" << std::endl;
    }

};

Эти объекты (Base na Derived) создаются и хранятся с использованием класса Manager и массива с именем groupedEntities:


constexpr std::size_t maxGroups = 32;
using Group = std::size_t;

class Manager
{
public:

    std::array<std::vector<Base*>, maxGroups> groupedEntities;

    void addToGroup(Base* mBase, Group mGroup)
    {
        groupedEntities[mGroup].emplace_back(mBase);
    }


    std::vector<Base*>& getGroup(Group mGroup)
    {
        return groupedEntities[mGroup];
    }

    template <typename T, typename... TArgs>
    T* addEnt(TArgs&&... mArgs)
    {
        T* e(new T(this));
        return e;
    }

};

Я создаю объекты и пытаюсь ссылаться на них они вот так:

void main() {

    std:size_t groupBlob = 0u;

    Manager* manager = new Manager();
    Derived* blob1(manager->addEnt<Derived>());
    Derived* blob2(manager->addEnt<Derived>());


    manager->addToGroup(blob1, groupBlob);
    manager->addToGroup(blob2, groupBlob);


    auto& grouped(manager->getGroup(groupBlob));

    for (auto& e : grouped)
    {
        e->speak();
        std::cout << e.DerviedVariable ;

    }


}

К сожалению, e.DerviedVariable недоступен, в то время как speak () функция говорит "класс Dervied говорит". Есть ли способ получить доступ к переменным производного класса с этой архитектурой? Спасибо

Ответы [ 2 ]

1 голос
/ 14 апреля 2020

Да, это возможно. Вам нужно только навести указатель. Простейший синтаксис:

((Derived*)e)->DerviedVariable

, который эквивалентен (по модулю константности, если таковой имеется) C ++ i sh

static_cast<Derived*>(e)->DerviedVariable

Слово «статический» здесь напоминает, что нет проверки во время выполнения: компилятор доверяет вам, что e действительно указывает на экземпляр Derived. Если это не так, происходит неопределенное поведение. Более безопасная альтернатива - dynamic_cast:

Derived *ee = dynamic_cast<Derived*>(e);
if (ee)
    x = ee->DerviedVariable;

Возвращает NULL, если объект не является экземпляром Derived. (Обратите внимание, что ссылки также могут быть преобразованы, но поскольку отсутствует ссылка NULL, dynamic_cast будет выбрасывать вместо этого, если приведение невозможно)

Тем не менее, использование таких приведений часто считается плохой практикой, для причина. Виртуальные функции предпочтительнее, в основном потому, что для их использования не требуется даже знать фактический тип объекта в точке вызова.

0 голосов
/ 14 апреля 2020

Вы можете использовать dynamic_cast в таких случаях. Выражение dynamic_cast<Derived*>(e), где e имеет тип Base*, будет иметь значение Derived*, если e действительно указывает на объект типа Derived, в противном случае оно будет иметь нулевой указатель.

if(Derived* d = dynamic_cast<Derived*>(e)) {
    std::cout << d->e.DerviedVariable;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...