Пожалуйста, рассмотрите следующий код:
#include <iostream>
using namespace std;
class superclass;
class subclass;
class subclass2;
class superclass
{
public:
unsigned int a;
superclass **superman;
};
class subclass : public superclass
{
public:
unsigned int b;
};
class subclass2 : public superclass
{
public:
unsigned int b;
};
class runner
{
public:
superclass **superman;
runner()
{
*superman=new superclass[2];
superman[0]=new subclass;
superman[0]->a=3;
superman[1]=new subclass2;
superman[1]->a=4;
}
};
int main() {
runner r;
cout<<r.superman[0]->a<<" "<<r.superman[1]->a;
return 0;
}
Как вы можете видеть, я хочу создать динамически размещенное хранилище ссылок на родительский класс, каждый из которых может затем указывать на дочерний класс, как только я не знаю, как извлечь дочерний класс снова из этого массива, чтобы я мог получить доступ к его переменная b;
Я попробовал следующие подходы, но они не сработали для меня и выдают ошибку
«преобразование из суперкласса * в нескалярный тип» подкласс «запрошено» и
«требуется преобразование из ‘суперкласса * в нескалярный тип’ subclass2 ‘»
subclass s1=r.superman[0];
subclass2 s2=r.superman[1];
Я уверен, что мне не хватает чего-то маленького.
PS: я не мог найти похожий вопрос, но если он существует, пожалуйста, перенаправьте меня,
Также я хотел бы решение, которое не требует от меня использовать вектор или любой встроенный
уже существующий класс библиотеки.
Вы действительно хотите умный указатель в этом случае, и суперкласс не должен иметь указатель на себя. Вы можете хранить указатель суперкласса в векторе, который указывает на реальный производный класс, так что полиморфизм все еще работает:
#include <memory>
#include <vector>
struct superclass
{
public:
superclass() : a(0) {}
virtual ~superclass() {} // it's important to define virtual destructor as superclass is a base class
int getA() const { return a; }
private:
unsigned int a;
};
class subclass : public superclass
{
public:
unsigned int b;
};
class subclass2 : public superclass
{
public:
unsigned int b;
};
class runner
{
public:
std::vector<std::unique_ptr<superclass>> superman;
runner()
{
superman.emplace_back(new subclass());
superman.emplace_back(new subclass2());
}
};
Тогда вы можете получить к нему доступ просто:
int main()
{
runner r;
std::cout << r.superman[0]->getA() <<" " < <r.superman[1]->getA();
return 0;
}
Примечание: скрывайте свои данные, если можете, обращайтесь к данным через функции set / get, не объявляйте участников открытыми.
superclass **superman;
runner()
{
*superman=...
Эти несколько строк кода дают неопределенное поведение коду. Вы не можете разыменовать неинициализированный указатель и ожидать, что все будет работать нормально.
Добавить virtual
деструктор в superclass
и использовать dynamic_cast
:
class superclass
{
public:
unsigned int a;
superclass **superman;
virtual ~superclass(){}; // You must at least have one virtual method
// in your superclass and destructor is good choice
// Otherwise, dynamic_cast wouldn't work:
// error: ... (source type is not polymorphic) !
};
// ...
// s1 and s2 must be pointers:
subclass *s1=dynamic_cast<subclass* >(r.superman[0]);
subclass2 *s2=dynamic_cast<subclass2*>(r.superman[1]);
//...
Примечание. Будьте внимательны при приведении из базового класса к производному классу. И не забудьте освободить выделенную память.