Как получить доступ из базового класса к методам и данным производного?
Есть примитивные классы:
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 шт):
Чтобы получить доступ к членам класса "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;
}
Что-то вроде такого
Оказалось был в шаге от решения. Достаточно добавить:
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.