Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> "Умная" работа с переменными-членами класса 
:(
    Опции темы
W4FhLF
Дата 13.3.2009, 19:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


found myself
****


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

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



Приветствую всех.

Есть такой, упрощённый, случай:

Код

class Body:
{
public:
     virtual ~Body();
};

class Sphere: public Body
{
     double radius;
public:
     virtual ~Sphere();
};

class Cone: public Body
{
     double radius;
     double height;
public:
     virtual ~Cone();
};

class Parallelepiped: public Body
{
     double width;
     double height;
     double length;
public:
     virtual ~Parallelepiped();
};

void setParams(Body* body)
{
     // Здесь необходимо задать параметры
}

int main(int argc, char* argv[])
{
     Body* b = new Cone();
     
     setParams(b);
}


Как создать наиболее рациональную реализацию setParams? 

Может есть паттерны или средства метапрограммирования(из того же boost'a)? Т.е. смысл в том, чтобы не завязываться на конкретном типе объекта наследника, а работать с данными-членами более гибко. Допустим по их именам(перечисление, задание, считывание...). 

Это сообщение отредактировал(а) W4FhLF - 13.3.2009, 19:06


--------------------
"Бог умер" © Ницше
"Ницше умер" © Бог
PM ICQ   Вверх
azesmcar
Дата 13.3.2009, 19:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

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



т.е. setParams должен понять какой ему тип передали и задать соответствующие параметры???

а если написать виртуальную функцию, Body сделать абстрактным и вызывать его? Или еще проще, устанавливать параметры в конструкторе конкретного обьекта.. Задача немного неясна, что именно должна делать фунцкяи setParams ??
PM   Вверх
andrew_121
Дата 13.3.2009, 19:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Кодофей
****


Профиль
Группа: Завсегдатай
Сообщений: 3448
Регистрация: 3.1.2008

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



    Заюзай enum в Body.


--------------------
Удалил аккаунт. Прощайте!
PM MAIL   Вверх
W4FhLF
Дата 13.3.2009, 19:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


found myself
****


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

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



Цитата(azesmcar @  13.3.2009,  19:19 Найти цитируемый пост)
а если написать виртуальную функцию, Body сделать абстрактным и вызывать его? Или еще проще, устанавливать параметры в конструкторе конкретного обьекта.. 


Это всё немного не то. 

Представь, что у нас 15 наследников Body и у каждого свой набор параметров. Допустим теперь, что в функции setParams тебе необходимо получить от пользователя необходимый набор параметров для переданного объекта body(ну в случае сферы ты печатаешь в консоли Radius и ждёшь ввода, в случае Cone печатаешь Radius, потом, после ввода радиуса, печатаешь Height и т.д.). Каковы твои действия? 


andrew_121, не понял.

Это сообщение отредактировал(а) W4FhLF - 13.3.2009, 19:44


--------------------
"Бог умер" © Ницше
"Ницше умер" © Бог
PM ICQ   Вверх
mes
Дата 13.3.2009, 19:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

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



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

Это сообщение отредактировал(а) mes - 13.3.2009, 20:02


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


любитель
****


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

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



вот немного с форума об этом:
http://forum.vingrad.ru/index.php?showtopic=234230
http://forum.vingrad.ru/index.php?showtopic=235416

Это сообщение отредактировал(а) mes - 15.3.2009, 15:47


--------------------
PM MAIL WWW   Вверх
AnLun
Дата 16.3.2009, 18:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Цитата(azesmcar @ 13.3.2009,  17:19)
т.е. setParams должен понять какой ему тип передали и задать соответствующие параметры???

а если написать виртуальную функцию, Body сделать абстрактным и вызывать его? Или еще проще, устанавливать параметры в конструкторе конкретного обьекта.. Задача немного неясна, что именно должна делать фунцкяи setParams ??

W4FhLF, а чем так плохо?
PM MAIL   Вверх
W4FhLF
Дата 20.3.2009, 11:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


found myself
****


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

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



AnLun, что именно? 


--------------------
"Бог умер" © Ницше
"Ницше умер" © Бог
PM ICQ   Вверх
Lazin
Дата 20.3.2009, 11:51 (ссылка)  | (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

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



Цитата(W4FhLF @  13.3.2009,  19:04 Найти цитируемый пост)
Как создать наиболее рациональную реализацию setParams? 

Может есть паттерны или средства метапрограммирования(из того же boost'a)? Т.е. смысл в том, чтобы не завязываться на конкретном типе объекта наследника, а работать с данными-членами более гибко. Допустим по их именам(перечисление, задание, считывание...). 

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

Код

class Body
{
Body* transform(const Matrix& m) const = 0;
void transform_inplace(const Matrix& m) = 0;
...
};

Body* Cone::transform(const Matrix& m) const
{
  Cone* c = new Cone(...параметры нового конуса...);
  return c;
}

void Cone::transform_inplace(const Matrix& m)
{
  ...вычисляем новые параметры объекта...
}


Это сообщение отредактировал(а) Lazin - 20.3.2009, 11:52
PM MAIL Skype GTalk   Вверх
GoldFinch
Дата 20.3.2009, 11:53 (ссылка)  | (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата



****


Профиль
Группа: Завсегдатай
Сообщений: 2141
Регистрация: 30.11.2008

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



а откуда setParams(Body*) возьмет значения параметров если они ей не передаются?
PM MAIL ICQ   Вверх
mes
Дата 20.3.2009, 12:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

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



Цитата(GoldFinch @  20.3.2009,  10:53 Найти цитируемый пост)
а откуда setParams(Body*) возьмет значения параметров если они ей не передаются? 


Цитата(W4FhLF @  13.3.2009,  18:43 Найти цитируемый пост)
Представь, что у нас 15 наследников Body и у каждого свой набор параметров. Допустим теперь, что в функции setParams тебе необходимо получить от пользователя необходимый набор параметров для переданного объекта body(ну в случае сферы ты печатаешь в консоли Radius и ждёшь ввода, в случае Cone печатаешь Radius, потом, после ввода радиуса, печатаешь Height и т.д.). Каковы твои действия? 


вот набросал условный пример работы :
Код


class FigureVisitor;

class Figure
{
    public:
     virtual ~Figure() {}
     virtual  void  Accept (FigureVisitor&) =0;
};
class Line : public Figure
{
    public:
        virtual  void  Accept (FigureVisitor&);
        void SetParam (const Point& pt1, const Point& pt2) {}

};

class Circle : public Figure
{
   public:
       virtual  void  Accept (FigureVisitor&);
       void SetParam (const Point& pt1, int Radius) {}
};

class Quad : public Figure
{
   public:
       virtual  void  Accept (FigureVisitor&);
       void SetParam (const Point& pt1, const Point& pt2) {}
};


class SetParamFromUserOperation : public FigureVisitor
{
     public:
        void Visit (Figure& fig) { fig.Accept (*this); }
        void Visit (Line & obj ) { ...  } // аналогично Circle
        void Visit (Circle& obj) { std::cout << "enter center & radius of circle"; Point pt; int Radius; cin>>pt; cin>>Radius; obj.SetParam(pt, Radius); }
        void Visit (Quad& obj)   { ... } // аналогично Circle
};

Line::  Accept (FigureVisitor& v) { v.Visit(*this); }
Circle::Accept (FigureVisitor& v) { v.Visit(*this); }
Quad::  Accept (FigureVisitor& v) { v.Visit(*this); }


int main ()
{
   Figure * fig = new Circle ();
   SetParamFromUserOperation ().Visit(*fig);
//...
   delete fig;
}



Это сообщение отредактировал(а) mes - 20.3.2009, 12:44


--------------------
PM MAIL WWW   Вверх
GoldFinch
Дата 20.3.2009, 12:36 (ссылка)    | (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата



****


Профиль
Группа: Завсегдатай
Сообщений: 2141
Регистрация: 30.11.2008

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



setParams(Body*) и Body::setParams() это одно и тоже, только 2е писать приятнее
PM MAIL ICQ   Вверх
Lazin
Дата 20.3.2009, 12:38 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

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



Цитата(W4FhLF @  13.3.2009,  19:43 Найти цитируемый пост)
Представь, что у нас 15 наследников Body и у каждого свой набор параметров. Допустим теперь, что в функции setParams тебе необходимо получить от пользователя необходимый набор параметров для переданного объекта body(ну в случае сферы ты печатаешь в консоли Radius и ждёшь ввода, в случае Cone печатаешь Radius, потом, после ввода радиуса, печатаешь Height и т.д.). Каковы твои действия? 

тогда, как сказал mes, можно использовать либо паттерн visitor, либо обычную виртуальную ф-ю, но есть один ньюанс

наиболее правильный ОО дизайн в этом случае, не строить огромную иерархию классов, состоящих их одних и тех-же элементов, а использовать композицию, то-есть выделить набор базовых примитивов (например point, angle, length) и создавать более сложные объекты на основе примитивных (например point, line(point, point), curve(point, point, point, point), rect(point, point, point, point), circle(point, length) etc) и создать механизм для поучения набора примитивных объектов из которых состоит более сложный объект
в этом случае, можно будет придумать generic версию ф-ии setParams
например, у нас есть набор объектов: Line, Circle, Rect
нам нужно полиморфно с ними работать, сначала мы получаем первый объект Body(Line), и получаем список его параметров { "Begin":point, "End":point } и выводим на экран просьбу ввести сначала Begin, а затем End. Потом берем следующий объект Body(Circle) - {"Radius":length, "Center Coord.":point } и так далее..
В общем случае, нужна возможность получить список параметров, причем не только самих параметров, но и их атрибутов, таких как название, значение по умолчанию, ограничения, все зависит от задачи.

Это сообщение отредактировал(а) Lazin - 20.3.2009, 12:40
PM MAIL Skype GTalk   Вверх
GoldFinch
Дата 20.3.2009, 12:43 (ссылка)   | (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата



****


Профиль
Группа: Завсегдатай
Сообщений: 2141
Регистрация: 30.11.2008

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



"печатаешь в консоли Radius и ждёшь ввода"
значит надо вводить классы Radius, Height, Width, Lenght
Код

class Dimention {
public:
double value;
virtual void Input()=0;
}
class Radius: public Dimention {
public: virtual void Input() { std::cout<<"Radius="; ... 


PM MAIL ICQ   Вверх
mes
Дата 20.3.2009, 12:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

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



Цитата(GoldFinch @  20.3.2009,  11:43 Найти цитируемый пост)
}
class Radius: public Dimention {
public: virtual void Input() { std::cout<<"Radius="; ... 

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

Это сообщение отредактировал(а) mes - 20.3.2009, 13:05


--------------------
PM MAIL WWW   Вверх
Страницы: (3) Все [1] 2 3 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

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

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


 




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


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

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