IMHO.WS

IMHO.WS (https://www.imho.ws/index.php)
-   Программирование (https://www.imho.ws/forumdisplay.php?f=40)
-   -   Гетерогенные объекты в С++ (https://www.imho.ws/showthread.php?t=92666)

Melkor 16.09.2005 00:58

Гетерогенные объекты в С++
 
Привет!
Есть небольшой вопросик.
Есть собрание объектов, класс Figure (виртуальный) из него выведен классы Line, Circle..etc c виртуальными ф-ями ...
Нужно создать класс-контейнер содержащий все вожможнык круги, линии и тд. с возможностью добавления/удаления элементов.
Есть идея использовать для этого вектор.
class Container
{
public:
// функции
private:
vector <Figure*> cont;
};

что-то такое и вызывать его по
Container a(new Line());
a.add(new Circle());

Вопрос!
как вызывать конструктор? стандартный тут не пойдет как я понял.
Нашел несколько примеров в нете, но там или вектор в main или используется array of Figure... (прям как в С)
Буду очень благодарен за помощь ибо уже крыша едет...

dyr_farot 16.09.2005 11:56

ничего не понял...
вызвать конструктор чей? контейнера? так зачем ему объект хранения передавать? объекта хранения? так в чем проблема с его вызовом?

PSyton 17.09.2005 09:18

Даествительно мутно написано.
Зачем делать прослойку, если контейнер содержит только вектор?
просто создаешь где надо
vector <Figure*> contaniner;

contaniner.push_back(new Line());
contaniner.push_back(new Circle());
...
contaniner.push_back(new Cube());

При этом абстаркатный класс Figure должен содержасть виртуальные методы, которые будут переопределны у потомков. И тогда конструкция типа
contaniner[10]->Drow();
будет замечательно работать.
Если есть какие-то специфичные методы, которые присущи только некоторым потомкам Figure, то можно заветси метод IsKindOf(), который будет говорить о том что это за потомок, после чего можно безболезненно приводить указтель к типу указателя на нужного потомка и работать.

Melkor 18.09.2005 03:05

Спасибо за ответы!
Сорри действительно странно получилось...
Идея была сразу же объект и создавать, чтобы сонструктор и делал .push_back(new Cube()); но что-то там не сошлость (так и не понял почему), поэтому написал отдельный метод в классе.

Figure содержит виртуальмые методы и все такое.
Прослойка нужна для простоты, это все будет массово обрабатываться.

Сейчас пытаюсь заставить програмку писать/читать это из файла. Господи... какая муть все это. В той книжке которую я читаю для этого предлагают создавать отдельный класс (который чуть ли не больше всего остального). Почему это нельзя просто сделать через if?
писать в формате: фигура, коорд 1, коорд 2

if фигура = круг
создать круг в контейнере
if фигура = квадрат
создать квадрат в контейнере
и тд.

alexey_ma 18.09.2005 10:35

Цитата:

Melkor:
Почему это нельзя просто сделать через if?
писать в формате: фигура, коорд 1, коорд 2
Это не OOП. При добавлении новых фигур придеться изменять код контейнера или код который добавляет обьекты в контейнер. На больших проектах это может привести к большим трудностям при сопровождении проекта. Такой код очень трудно модифицировать, добавлять какие-то новые возможности.

PSyton 18.09.2005 11:12

согласен с alexey_ma
лино я поступил бы примерно так (очень примерно):

Код:

//для Figure завел бы методы, в качестве параметров которым был бы,
//к примеру, дескриптор открытого файла.
virtual bool Read(int rFile);
virtual bool Write(int wFile);
//естественно для каждой фигуры переписал этот метод так чтобы
//она умела читать и писать инфу о себе в нужном виде.
//так же завел бы где-нибудь

Figure *CreateFigure(const figuretype &ft) 
{
  swtich(ft)
  {
  case circle:
    return (Figure *)new Circle();
    ...   
  case cube:
    return (Figure *)new Cube();
  }
  return (Figure *) new UnsupportedFigure(); //Ну или Exception выкидывать
}
//После чего в контейнере метор Read будет выглядеть примерно так.   

{
  int mFile;
  //Открываем файл и читаем из него инфу всякую. потом доходим до
  //самих фигур и читаем тип первой 
  while (!end)
  {
    Figure *newf=CreateFigure(readtype);
    newf->Read(mFile);
    m_storage.push_back(newf);
  }
  //Закрываем файл все прочитано
}
//Метод Write контейнера еще проще: 
{
  int mFile;
  //Открываем файл и пришем в него инфу всякую
  for (vector<Figure*>::const_iterator iter=m_storage.begin();
        iter!=m_storage.end();iter++)
    (*iter)->Write(mFile); 
  //Закрываем файл все записано
}

Естественно это просто набросок на вскидку, но уже здесь для добавления поддержки новых фигур в контейнере переписывать почти ничего не придется.

Melkor 18.09.2005 13:47

Цитата:

PSyton:
//для Figure завел бы методы, в качестве параметров которым был бы,
//к примеру, дескриптор открытого файла.
virtual bool Read(int rFile);
virtual bool Write(int wFile);
не совсем понял зачем этот дискриптор нужен. Мож посылать ifstrem/ofsream на нужный фалй?

Цитата:

PSyton:
Figure *newf=CreateFigure(readtype);
как это будет работать? readtype должен считывать из файла, тот же самый if?

PSyton 18.09.2005 18:48

Ну дескриптор, поток или CFile& разницы особой нет. Хотя поток пожадуй даже лучше.
Да с readtype это тот же самй if, только здесь чтение данных о самой фигуре ложится не на класс контейнера, на класс конкретной фигуры. ВСе что требуется в таком случае от контейнера, то вызывать методы фигур, даже не догадываясь о том как они читают/пишут и хранят данные.

3DRaven 19.09.2005 10:38

Погугли: "Двойная диспетчеризация","Фабричный метод","Шаблонный метод","Сериализация", и для удобства "XML". Это спасет отца русской демократии :)


Часовой пояс GMT +4, время: 02:01.

Powered by vBulletin® Version 3.8.5
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.