Поиск:

Ответ в темуСоздание новой темы Создание опроса
> ООП в builder c++, некоторое затруднение в реализации 
:(
    Опции темы
wolver17
  Дата 13.2.2015, 17:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 45
Регистрация: 15.5.2011

Репутация: 1
Всего: 1



Собственно, есть определённый код класса Parent и его двух дочерних public-классов Сhild1 и Сhild2. Есть виртуальная ф-ция Processing, которая рассчитывает значения трёх переменных, вводимых через компонент TEdit.
Код

class Parent
{
protected:
        float one;   
        float two;  
        float three;       
public:
        Parent(float, float, float);
        ~Parent()
        {};
        virtual float Processing()
        {
        return(0);
        }
        float Get_one();
        float Get_two();
        float Get_three();
        float Get_something();
};
//--------------------------
class Сhild1: public Parent  
{
public:
        Сhild1(float t_one, float t_two, float t_three):Parent(t_one, t_two, t_three) { }
        ~Сhild1()
        {};
        float Processing()
        {
        float p=one*two*three;
        Form2->StringGrid1->Cells[1][1]=FloatToStrF(p,ffFixed,5,5);
        return(0);
        }
};
//--------------------------
class Сhild2: public Parent
{
public:
        Сhild2(float t_one, float t_two, float t_three):Parent(t_one, t_two, t_three) { }
        ~Сhild2()
        {};
        float Processing()
        {
        float p=one+two+three;
        Form2->StringGrid1->Cells[1][1]=FloatToStrF(p,ffFixed,5,5);
        return(0);
        }
};
Parent a(0,0,0);
Parent* x[2];
TForm2 *Form2;
//---------------------------------------------------------------------------
__fastcall TForm2::TForm2(TComponent* Owner)
        : TForm(Owner)
{
}

//================реализация классовых ф-ций===================
Parent::Parent(float t_one, float t_two, float t_three)
{
        one=t_one;
        two=t_two;
        three=t_three;
}
//----------------------------------
float Parent::Get_one()
{
   one=StrToFloatDef(Form2->Edit1->Text,0); 
return(0);
}
//аналогично с Get_two и Get_three со своих Edit2 и 3.
//---------------------------------
float Parent::Get_something()
{
   x[0] = new Сhild1(one,two,three);
   x[0]->Processing();
return(0);
}
//======================================================
void __fastcall TForm2::RadioButton1Click(TObject *Sender)
{
   a.Get_something();
}

void __fastcall TForm2::RadioButton2Click(TObject *Sender)
{
   a.Get_something();
}


1) Вопрос, как правильно с точки зрения ООП, повестись с ф-цией Get_something, чтобы она могла обрабатывать значения полиморфной вирт. ф-ции в зависимости от того, какой x[i] определён в коде. 
Если подход в описании классов сделан правильно, то в идеале хотелось бы что-то вроде:
Код

//переменная i - где-то описана
float Parent::Get_something()
{
   тип func=преобразование имени ф-ции в строку Сhild+i
   x[i] = new func (one,two,three);
   x[i]->Processing();
return(0);

Если нет, то как переформировать описание и реализации той части класса, которую вы считаете нужным поменять? Пож. с примером.

2) можно ли описать Event метода для TRadioButton - RadioButton1Click как friend какому-либо с классов и внести описание x[i] в тело этого Event ?
Код

void __fastcall TForm2::RadioButton1Click(TObject *Sender)
{
   x[0] = new Сhild1(one,two,three);
   x[0]->Processing();
}

PM MAIL   Вверх
Alexeis
Дата 13.2.2015, 19:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 26
Всего: 459



 Это фигня называется Фабричный метод https://ru.wikipedia.org/wiki/%D0%A4%D0%B0%...BD%D0%B8%D1%8F)

Делается это примерно таким образом. Прячем конструктор чайлдов в приват и пишем 3 функции заменяющие конструктор. По одной для каждого класса. 
Функция типа
Код

Parent* CreateChild1(...)
{
   return new Child1(...);
}

Делаем функции френдами своих классов - (чтобы был доступен приватный конструктор) .
После чего описываем тип функции 
Код

typedef Parent* (tfabr_meth)(...);

Нам нужно будет сохранить указатели на эти порождающие функции зарядить в ассоциативный массив std::map
Описываем сам массив

Код

std::map<std::wstring, tfabr_meth> fabr_map;


Заряжаем в него все наши функции

Код

fabr_map.insert(std::make_pair<std::wstring, tfabr_meth>(L"Child1", CreateChild1);
....


И создаем собственно сам фабричный метод

Код

Parent* CreateAnyChild(std::wstring child_name, ....)
{
  std::map<std::wstring, tfabr_meth>::iterator it = fabr_map.find(child_name);
  if (it != fabr_map.end())
     return (it->second)(....); //вызываем одну из функций CreateChildX по сохраненному адресу.
  else
    return NULL; // не нашлось класса с нужным именем
}


Там, кстати на вики есть еще более простой пример на С++ без всяких STLей.

Это сообщение отредактировал(а) Alexeis - 13.2.2015, 19:34


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
wolver17
Дата 13.2.2015, 20:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 45
Регистрация: 15.5.2011

Репутация: 1
Всего: 1



Что-то этот фабричный метод сложноват для восприятия... особенно если ни разу такое не далал)

Цитата(Alexeis @  13.2.2015,  19:16 Найти цитируемый пост)
Прячем конструктор чайлдов в приват и пишем 3 функции заменяющие конструктор. По одной для каждого класса. 

Так дочерних классов 2, значит 2 констр. в приват а мейн конструктор без изменения?
--------------------------------------------------------------
Пока так:
Код

#include <map> 

class Parent
{
protected:
        float one;    
        float two;  
        float three;
public:
        Parent(float, float, float);
        ~Parent()
        {};
        virtual float Processing()
        {
        return(0);
        }
        float Get_one();
        float Get_two();
        float Get_three();
        float Get_something();
};
//--------------------------
typedef Parent* (tfabr_meth)(); // надо ли так? -> typedef Parent* (tfabr_meth)(float t_one, float t_two, float t_three);
std::map<std::wstring, tfabr_meth> fabr_map;

class Child1: public Parent  
{
public:
        friend Parent* CreateChild1(float t_one, float t_two, float t_three)
        {
                return new Child1(t_one, t_two, t_three);
        }
        ~Child1()
        {};
        float Processing()
        {
        float p=one*two*three;
        Form2->StringGrid1->Cells[1][1]=FloatToStrF(p,ffFixed,5,5);
        return(0);
        }
private:
        Child1(float t_one, float t_two, float t_three):Parent(float t_one, float t_two, float t_three) { }
};
//class Child2 аналогично
//----------------------
void __fastcall TForm2::RadioButton1Click(TObject *Sender)
{
   fabr_map.insert(std::make_pair<std::wstring, tfabr_meth>(L"Child1", CreateChild1));
   a.Get_something();
 }

------------------------------------
на эту ф-цию с её телом - компилятор выдаёт кучу разнообразных ошибок:
Parent* CreateAnyChild(std::wstring child_name, ....)
{}


Это сообщение отредактировал(а) wolver17 - 13.2.2015, 21:17
PM MAIL   Вверх
Alexeis
Дата 17.2.2015, 11:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 26
Всего: 459



Код

typedef Parent* (tfabr_meth)(float t_one, float t_two, float t_three)

тип должен соответствовать типу функции - конструктора CreateChildX.

CreateChild1 я подразумевал что будет определена вне класса, иначе зачем ее делать friend? friend - разрешает функции, которая не является функцией класса получать доступ к private полям и функциям класса. функции класса это умеют по определению. Кроме того нельзя вызывать никакие функции класса до вызова его конструктора (кроме статических) .

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



--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
wolver17
Дата 18.2.2015, 04:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 45
Регистрация: 15.5.2011

Репутация: 1
Всего: 1



Цитата(Alexeis @  17.2.2015,  11:27 Найти цитируемый пост)
CreateChild1 я подразумевал что будет определена вне класса, иначе зачем ее делать friend? friend - разрешает функции, которая не является функцией класса получать доступ к private полям и функциям класса.

Простите, но вы не правы: "Функция может стать другом класса, если в его описании она описана как friend." © Страуструп. К тому же я читал на одном форуме по ООП, что для френд абсолютно до лампочки куда лепить в паблик или привейт - эти права доступа не влияют на френд.
Цитата(Alexeis @  17.2.2015,  11:27 Найти цитируемый пост)
Пожалуй, что этот пример для вас сложноват, попробуйте пример из википедии. 

Тут вы абсолютно правы) Фабричный метод для меня сложен, попробую пересобрать код с вики под свои классы. Но возможно ваша помощь в нюансах кодинга будет нужна))

PM MAIL   Вверх
Alexeis
Дата 18.2.2015, 17:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 26
Всего: 459



Цитата(wolver17 @  18.2.2015,  05:02 Найти цитируемый пост)
К тому же я читал на одном форуме по ООП, что для френд абсолютно до лампочки куда лепить в паблик или привейт - эти права доступа не влияют на френд.

  Я про то, что  у вас тело функции определено внутри класса. Это автоматически делает функцию методом класса. Такие функции первым параметром получают указатель на экземпляр класса this, а как такое может сработать если функция должна создать экземпляр этого класса? Разве что статической объявить.


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
wolver17
Дата 10.3.2015, 21:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 45
Регистрация: 15.5.2011

Репутация: 1
Всего: 1



Покопался в куче инфы о фабричном методе (в книге Александреску - Современное проектирование на C++ и нескольких статьях на Хабре - фабрика объектов и фабрика фабрик) в связке с контейнером <map> + основываясь на примере Классическая реализация паттерна Factory Method попытался перефразировать свой код, приведя его к фабрике. Однако если в случае с последней ссылкой удалось переделать реализуемое там сохранение объектов в vector'e под свой map, то при попытке повторить всё на своём коде застопорилось на ошибках, решение которых я не могу найти(
Собственно код ниже:
Код

//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
#include <map>
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
//---------------------------------------------------------------------------
using namespace std;
class Parent
{
protected:
        float one;
        float two;  
        float three;
public:
        //Parent(float, float, float);
        virtual ~Parent()
        {};
        virtual float Processing()
        {
        return(0);
        }
        float Get_one();
        float Get_two();
        float Get_three();
        float Get_something();
};
//--------------------------
class Child1: public Parent
{
public:
        //Child1(float t_one, float t_two, float t_three):Parent(t_one, t_two, t_three) { }
        ~Child1()
        {};
        float Processing()
        {
        float p=one*two*three;
        Form2->StringGrid1->Cells[1][1]=FloatToStrF(p,ffFixed,5,5);
        return(0);
        }
};
//--------------------------
class Child2: public Parent
{
public:
       // Child2(float t_one, float t_two, float t_three):Parent(t_one, t_two, t_three) { }
        ~Child2()
        {};
        float Processing()
        {
        float p=one+two+three;
        Form2->StringGrid1->Cells[1][1]=FloatToStrF(p,ffFixed,5,5);
        return(0);
        }
};
//--------------------------
// фабрика объектов
class Factory
{
protected:
        float one;
        float two;  
        float three;
public:
        virtual Parent* createParent()=0;//(float, float, float) = 0;
        virtual ~Factory() {}
};
  
class Child1Factory: public Factory
{
public:
    Parent* createParent()//(float t_one, float t_two, float t_three)
    {
       /* one=t_one;
        two=t_two;
        three=t_three;*/
      return new Child1();//(t_one, t_two, t_three);
    }
};
  
class Child2Factory: public Factory
{
  public:
    Parent* createParent(){//(float t_one, float t_two, float t_three) {
      return new Child2();//(t_one, t_two, t_three);
    }
};
//Parent a(0,0,0);
Parent* x[2];
TForm2 *Form2;
//---------------------------------------------------------------------------
__fastcall TForm2::TForm2(TComponent* Owner)
        : TForm(Owner)
{
}
//================реализация классовых ф-ций===================
/*Parent::Parent(float t_one, float t_two, float t_three)
{
        one=t_one;
        two=t_two;
        three=t_three;
} */
//----------------------------------
float Parent::Get_one()
{
   one=StrToFloatDef(Form2->Edit1->Text,0);
return(0);
}
//аналогично с Get_two и Get_three со своими Edit2 и 3.
//---------------------------------
float Parent::Get_something()
{
   //x[0] = new Child1(one,two,three);
   //x[0]->Processing();
return(0);
}
//======================================================
void __fastcall TForm2::RadioButton1Click(TObject *Sender)
{
   //a.Get_something();
   int i=1;
   typedef map<AnsiString,Factory*> TMap; //создаём контейнер с ключём типа AnsiString и типом значения указатель на класс
   TMap map;
   Child1Factory* child1_factory = new Child1Factory;
    map.insert(pair<AnsiString,Factory*>("Child"+IntToStr(i),child1_factory->createParent()));//(one, t_two, t_three)));
}
//---------------------------------------------------------------------------
void __fastcall TForm2::RadioButton2Click(TObject *Sender)
{
   //a.Get_something();
   Child2Factory* child2_factory = new Child2Factory;
}
//---------------------------------------------------------------------------


А вот тот код, переделанный под map с сайта. В чём же ошибка, что не так описано в моей фабрике?
компилятор выдаёт, если делать без параметров createParent():
[C++ Error] Unit1.cpp(129): E2285 Could not find a match for 'pair<AnsiString,Factory *>::pair(AnsiString,Parent *)'
если параметризированную (как я думаю она должна быть, т.к. изначально конструктор классов был параметрическим):
то выдаёт гораздо больше ошибок, на return new Child1(t_one, t_two, t_three) - что не может найти подходящий конструктор Child1::Child1(...
на строчку с мап.инсерт и на что-то ещё.
Короче я запутался, помогите пож.!

Присоединённый файл ( Кол-во скачиваний: 1 )
Присоединённый файл  Unit1.cpp 3,04 Kb
PM MAIL   Вверх
xvr
Дата 11.3.2015, 11:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 48
Всего: 223



  • Ваша factory должна находится вне метода (быть членом класса), иначе толку от нее нет - ею невозможно воспользоваться
  • В map нужно класть саму factory, а не то, что она произвела map.insert(pair<AnsiString,Factory*>("Child"+IntToStr(i),child1_factory));


PM MAIL   Вверх
Alexeis
Дата 11.3.2015, 14:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 26
Всего: 459



Цитата(xvr @  11.3.2015,  12:28 Найти цитируемый пост)
В map нужно класть саму factory, а не то, что она произвела map.insert(pair<AnsiString,Factory*>("Child"+IntToStr(i),child1_factory));

  Проще говоря строчка child1_factory->createParent() выполнит вызов функции createParent(), а нам не требуется вызова функции, а лишь сохранение ее адреса в объекте класса pair


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
wolver17
Дата 11.3.2015, 23:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 45
Регистрация: 15.5.2011

Репутация: 1
Всего: 1



Цитата(xvr @  11.3.2015,  11:28 Найти цитируемый пост)
В map нужно класть саму factory

спс, изменил - ошибка пропала)

Цитата(xvr @  11.3.2015,  11:28 Найти цитируемый пост)
Ваша factory должна находится вне метода (быть членом класса), иначе толку от нее нет - ею невозможно воспользоваться

мне загнать 
Код

typedef map<AnsiString,Factory*> TMap; 
TMap map;

в public класса Factory или что вы имели ввиду? поясните пож. на коде...

Цитата(Alexeis @  11.3.2015,  14:02 Найти цитируемый пост)
child1_factory->createParent() выполнит вызов функции createParent()

спс за доп. коммент)

PM MAIL   Вверх
xvr
Дата 12.3.2015, 15:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 48
Всего: 223



Цитата(wolver17 @  11.3.2015,  23:20 Найти цитируемый пост)
в public класса Factory

Именно так

PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++ Builder"
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

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

  • Литературу по С++ Builder обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Настоятельно рекомендуем заглянуть в DRKB (Delphi Russian Knowledge Base) - крупнейший в рунете сборник материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C++ Builder | Следующая тема »


 




[ Время генерации скрипта: 0.0758 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.