Как получить доступ из базового класса к методам и данным производного?

Есть примитивные классы:

class B {
public:
    virtual ~B() { }
};

template <typename T>
class D : public B {
public:
    T _valD;
    D(T x) { _valD = x; };
};

Далее:

B* _bp = nullptr;
// Какой то код...
_bp = new D<double>(3.24);
_bp = reinterpret_cast<D<double>*>(_bp);

Теперь хотелось бы получить доступ через указатель _bp к свойству D._valD. Что-то типа _bp->_valD. В книгах написано, что указателю базового класса можно присвоить адрес производного (так называемый полиморфизм), но при этом через указатель на базовый класс получить доступ к методам производного нельзя, за исключением виртуальных методов. Хотя существует оговорка: нужно выполнить приведение указателя базового класса к производному. Но вот как сделать это приведение и получить доступ через указатель базового класса к обычным методам и свойствам производного понять не могу. Дайте пожалуйста ответ: такое в принципе возможно в С++? И если возможно, то как доработать вышеуказанный код?

P.S. Пробовал dynamic_cast. Безуспешно. Если смотреть на _bp через отладчик, то он содержит в себе значение _valD, но как до него добраться, непонятно.


Ответы (2 шт):

Автор решения: beccapana

Чтобы получить доступ к членам класса "D", нужно использовать dynamic_cast, но нужно удостовериться, что класс B имеет хотяб 1 виртуальный метод

#include <iostream>

class B {
public:
    virtual ~B() { }
    // Добавим виртуальную функцию, чтобы dynamic_cast работал
    virtual void dummy() {}
};

template <typename T>
class D : public B {
public:
    T _valD;
    D(T x) { _valD = x; };
};

int main() {
    B* _bp = nullptr;

    // Присваиваем указатель на объект D<double>
    _bp = new D<double>(3.24);

    // Приводим указатель к D<double>* с помощью dynamic_cast
    if (auto* d_ptr = dynamic_cast<D<double>*>(_bp)) {
        // Теперь можем получить доступ к _valD
        std::cout << d_ptr->_valD << std::endl;
    }

    // Не забудем освободить выделенную память
    delete _bp;

    return 0;
}

Что-то вроде такого

→ Ссылка
Автор решения: Vladimir Bogdanov

Оказалось был в шаге от решения. Достаточно добавить:

auto value = (*(D<double>*)_bp)._valD;

В итоге, переменная value получает и значение, и ей назначается тип от D._valD (в данном случае double).

Дальше можно проделать следующее:

delete _bp;
_bp = new D<int>(3);
auto value2 = (*(D<int>*)_bp)._valD;

Теперь переменная value2 получит значение и тип int.

→ Ссылка