полиморфное конструирование объектов
От: Serrega США http://sergeyteplyakov.blogspot.com/
Дата: 21.12.04 15:59
Оценка:
Существует иерархия классов (некоторые функции опущены для упращения)
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).
При этом хотелось бы сваять наиболее простое полиморфное получение этих данных из этого самого хранилища.
Я это попытался реализовать следующим образом:

Расширяем базовый класс:
class Base
{
public:
Base(EClassType type){m_type = type;}
virtual ~Base(){}
EClassType GetBaseType() const {return m_type;}
virtual std::ostream& Save(std::ostream &s) const = 0;
virtual std::istream& Load(std::istream &s) = 0;
friend std::ostream& operator<<(std::ostream &s, const CBase &base)
{
s<<m_type;
return base.Save(s);
}
friend std::istream& operator>>(std::istream &s, CBase &base)
{
s>>base.m_type; //для простоты не проверяю ошибки
}
private:
EClassType m_type;

};//class Base

Реализую в производных классах соответствующие виртуальные функции 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);
}

}
Таким образом в классе С осуществляется полиморфное создание набора объектов.
Хотелось бы обсудить эту проблему и пути ее решения.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.