Существует иерархия классов (некоторые функции опущены для упращения)
class Base
{
public:
Base(EClassType type){m_type = type;}
virtual ~Base(){}
EClassType GetBaseType() const {return m_type;}
private:
EClassType m_type;
};//class Base
Не кричите сразу же по поводу хранения имени типа в базовом классе, дочитайте все-таки до конца.
Существуют производные классы:
class Derive1 : public Base;
class Derive2 : public Base;
class Derive3 : public Base;
Есть некий класс С, который хранит массив указателей на Base.
class C
{
public:
bool AddClass(EClassType type);
private:
std::vector<Base*> m_vBases;
}; //class C
Создание экземпляров Derive1-3 осуществляется с помощью BaseCreator:
class BaseCreator
{
BaseCreator();
public:
~BaseCreator();
//почти "виртуальный" конструктор
Base* CreateBase(EClassType type) //фукнция вертает NULL, если не удалось создать экземпляр класса
{
switch(type)
{
case type1: return new Derive1(type);
case type2: return new Derive2(type);
case type2: return new Derive3(type);
default: return NULL;
}
}
//статический тип возвращаемого значения Base, динамический — Derive1-3.
};//class BaseCreator
Добавление элементов Base в класс С осуществляется пользователем в процессе работы программы, после чего
данные сохраняются в некоторое хранилище (сейчас просто в файл черер std::iostream).
При этом хотелось бы сваять наиболее простое полиморфное получение этих данных из этого самого хранилища.
Я это попытался реализовать следующим образом:
Реализую в производных классах соответствующие виртуальные функции Load и Save.
В BaseCreator добавляю функцию создания класса из потока:
Base* BaseCreator::CreateBase(std::istream &s)
{
Base base; s>>base;
Base *pBase = CreateBase(base.GetBaseType());
if ( !pBase ) return NULL;
pBase->Load(s);
return pBase;
}
и в класс С добавляю операторы помещения в поток и считывания из потока:
friend std::ostream& operator<<(std::ostream &s, const C &c)
{
s<<static_cast<int>(c.m_vBase.size());
for (size_t i = 0; i < c.m_vBase.size(); ++i)
{
s<<*c.m_vBase[i]<<" ";
}
}
friend std::istream& operator>>(std::istream &s, C &c)
{
int vSize = 0; s>>vSize;
if ( vSize )
{
Base* pBase = theCreator().CreateBase(s);
if ( pBase )
c.m_vBases.push_back(pBase);
}
}
Таким образом в классе С осуществляется полиморфное создание набора объектов.
Хотелось бы обсудить эту проблему и пути ее решения.