Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Вызов в конструкторе методa класса


Автор: knut 31.1.2007, 19:22
Добрый день.
Вот столкнулся с такой проблемой.
Есть класс   наследник класс CSomeClass(наследноков много)  и есть класс CParser у класса CParser есть метод 
void Load(const char*pFilename) // загрувает xml фаил. 
Теперь в конструкторе CSomeClass в вызваю метод CParser a Load(const char*pFilename) чтоб прочетать из фаила  данные  и инецализировать мемберы класса CSomeClass а.
Вопрос. 
Как передаьт в Load  метод обект SomeClass а ?в качестве парамерта Load a нельзя.
Код

class CSomeClass:public cBase
{
  CSomeClass()
{
  ob.Load(pFilename); // но в Load надо передать обект CSomeClass чтоб иницализовать 
                                  //мемберыданного класса
}
  
};
class cParser
{
   void Load(pfilename)
{
   //но здес нужен обект того класс чей конструктор вызвал Load()
   // парсим файл.
}
}

Автор: Anikmar 31.1.2007, 19:28
Класс-родитель ничего не знает о методах и свойствах наследника. 

Автор: JackYF 31.1.2007, 20:45
Цитата(knut @  31.1.2007,  19:22 Найти цитируемый пост)
Как передаьт в Load  метод обект SomeClass а ?в качестве парамерта Load a нельзя.

почему?

Автор: Anikmar 31.1.2007, 20:47
Объект нельзя, а локальный параметр типа AnsiString можно

Автор: knut 1.2.2007, 11:31
Цитата

Класс-родитель ничего не знает о методах и свойствах наследника.

а ему  и не надо

Автор: Daevaorn 1.2.2007, 12:14
Цитата(knut @  1.2.2007,  12:31 Найти цитируемый пост)
а ему  и не надо 

вот тебе точно надо научиться по человечески задовать вопросы, если хочешь получать на них правильные ответы

Автор: Vyacheslav 1.2.2007, 13:17
Что то тут с логикой не то. 
Я подобную систему решалпримерно так.  Исходим из того, что cParser
- это SAX парсер и при распарсивании он генерит события 
Тогда
Код

class CBase
typedef void (* EventHandler) (cBase*, const string& value); 
typedef map<string, EventHandler > Handlers;
typedef Handlers::value_type HandlersValue;  

class cBase
{
protected:
      //метод для регистриции обработчиков для присвоения( сеттеры) значения полям
       void field_register( const string& name,   EventHandler ) {
            m_handlers.insrteventHandler ( name,  EventHandler );
       }
public:
      // присваиваем полю с именем name значение value
       void set_field( const string& name, const string value ) {
            Handlers::iteratot result = m_handlers.find(name);
    if (result != m_handlers.end()) {
        EventHandler handler = (*result).second;
                                handler(this, value);
                }
       } 
private:
  Handlers m_handlers;
 };

class CSomeClass:public cBase
{
  CSomeClass()
 {
   //регистрируем обработчики для полей, появившихся в данном классе 
   field_register("a", set_a_member);
   field_register("b", set_a_member);
 }
  //обработчик, который выполняет присвоение полю
  // естесвенно, если поле не string, то в нем надо будет выполнить преобразование string to type
  static void set_a_member( CBase* obj,  string value) {
         if( CSomeClass *someClass = dynamic_cast<CSomeClass*>(obj) ) {
                a= value;
         }           
  }

   static void set_b_member( CBase* obj,  string value) {
         if( CSomeClass *someClass = dynamic_cast<CSomeClass*>(obj) ) {
                b= value;
         }           
  }
private: 
  string a;
  string b;
}

class CSomeClass1 :CSomeClass
{
  CSomeClass1()
 {
   //регистрируем обработчики для полей, появившихся в данном классе 
   field_register("c", set_c_member);
   field_register("d", set_d_member);
 }
  static void set_a_member( CBase* obj,  string value) {
         if( CSomeClass1 *someClass = dynamic_cast<CSomeClass1*>(obj) ) {
                c= value;
         }           
  }

   static void set_b_member( CBase* obj,  string value) {
         if( CSomeClass1 *someClass = dynamic_cast<CSomeClass1*>(obj) ) {
                d= value;
         }           
  }
private 
  string c;
  string d;
}


class cParser
{
   void Load(CBase* obj, pfilename )
   {
       // здесь  парсим и при получении имени поля и его значения name, value делаем присвоение
       obj->set_field(name, value);
   
   }
}



Код

 CSomeClass1  someClass;
  cParser().Load(&someClass, fileName);


А вообще можно еще  определить оператор >> 
Код

CSomeClass1  someClass;
 cParser(FileName) >> someClass;






Автор: knut 1.2.2007, 15:18
есть класс cParser 
Код

class cParser 
{
public:
 void Load(const char *pFilename);
 void Add_Element(const char *pFilename,int x,int y,cBase::E_Type,cBase*);//Добавляет элемент в xml фаил   (т.е обект тира cUnit) 
};

елсть класс
Код


class cSomeClass:public cBase
{
  cSomeClass()
{ob.Add_element(.......,cSomeClass*)}//вызов Add_Element a 
 /// members
public:
        int value;
      ///....
  }


теперь если xотим создать обект т.е ( добавляем элемент в xml )
cSomeClass *pt = new cSomeClass; a в конструкторе cSomeClass вызеваем Аdd_Element(...,pt)
создали элемент и добавили в фаил.
Собственно  и вот проблема.
Надо инизализовать мемберы cSomeclass a после того как добавили элемент в фаил.

Автор: Vyacheslav 1.2.2007, 17:36
Цитата(knut @  31.1.2007,  19:22 Найти цитируемый пост)
Есть класс   наследник класс CSomeClass(наследноков много)  и есть класс CParser у класса CParser есть метод 
void Load(const char*pFilename) // загрувает xml фаил. 
Теперь в конструкторе CSomeClass в вызваю метод CParser a Load(const char*pFilename) чтоб прочетать из фаила  данные  и инецализировать мемберы класса CSomeClass а.



Цитата(knut @  1.2.2007,  15:18 Найти цитируемый пост)

cSomeClass *pt = new cSomeClass; a в конструкторе cSomeClass вызеваем Аdd_Element(...,pt)
создали элемент и добавили в фаил.
Собственно  и вот проблема.




Не кажется Вам , что в эти два абзаца описывают совершенно противоположные процессы?
Первый абзац  описывант процедуру создания объекта и иyциализации его членов, данными из xml, что очень близко напоминает десериализацию
Второй  абзац больше похож на обратный процесс. 
Или я опять ничего не понял?



Автор: Anikmar 1.2.2007, 18:18
Если в метод Add_Element должен передаваться объект некого класса, у которого этот метод должен произвести инициализацию некоторых полей и свойств, значит Add_Element должен знать эти свойства для каждого переданного класса.
Либо он должен знать что сделать с каждым конкретным классом, либо для него это должен быть один некий класс с известными ему свойствами.

1 Вариант
Следовательно все эти свойства должны находиться в базовом классе, и этот метод спокойно их инициализирует. А передавать ему нужно объект базового класса.

2. Вариант
Если все производные классы, передаваемые в метод Add_Element имеют различные методы, которые требуются инициализировать - то тогда этот метод должен знать структуру переданного ему объекта. Т.е. в таком случае они тоже должны иметь общий базовый класс, а в методе Add_Element при помощи dynamic_cast  определеять конкретно какого класса объект был ему передан и инициализировать его.

Автор: Vyacheslav 1.2.2007, 18:42
Цитата(Anikmar @  1.2.2007,  18:18 Найти цитируемый пост)
 а в методе Add_Element при помощи dynamic_cast  определеять конкретно какого класса объект был ему передан и инициализировать его. 

И при добавлении нового класса каждый раз переписывать Add_Element smile
Я же показал выше код, который относительно усешно решает такую задачу. При этом  Parser понтия не имеет с полях, которые он инициализирует



Автор: Anikmar 1.2.2007, 19:10
Цитата(Vyacheslav @  1.2.2007,  18:42 Найти цитируемый пост)
И при добавлении нового класса каждый раз переписывать Add_Element 
Я же показал выше код, который относительно усешно решает такую задачу. При этом  Parser понтия не имеет с полях, которые он инициализирует


Полностью согласен - поэтому предложил 1-й вариант более предпочтительнее - примерно то же самое, что и у вас, только несколько упрощеннее и менее функционально, естественно. Т.е. в базовом классе либо находятся заранее известные поля, либо заранее известные методы (виртуальные), которые известны и вызываются из парсера.

При написании порожденного класса либо надо зарегистрировать методы установки либо переопределить виртуальные - все зависит от конкретного применения.

Ваш метод более универсален, мой метод проще для понимания.

Автор: knut 1.2.2007, 22:25
если при создание обектаов  (наследников)  полья классов иницализуются одинакого (для каждого класса)то то почему не иницализовать иx прям в конструкторе  а потом при вызове Аdd_Elemet() получить иx и записать в фаил.
P.S по моему это в полне логичная организаьцыя smile ато и я запутолся и вас запуталsmile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)