Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Параметры в конструкторе  (Прочитано 28481 раз)
0 Пользователей и 5 Гостей смотрят эту тему.
Scorp__)
Молодой специалист

ru
Offline Offline
Пол: Мужской

« : 27-07-2007 09:50 » 

Давно меня мучает такой вопрос и внятного ответа в книжках я на него не нашел.

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

Но что делать, когда у объекта десяток полей или больше и все они имеют значение для его работоспособности? Длинный список аргументов - некузяво. Заполнение полей по умолчанию также не выход, потому что сложно выделить наиболее популярные значения.

Пока мне приходит в голову только одно: упаковать все параметры в структуру, предоставить ее интерфейс пользователю и передавать конструктору указатель на эту структуру. Но вроде как выходит введение новой сущности; кроме объекта есть еще "поля объекта".

Может быть кто-то знает общепринятое решение? Или хоть какое-нибудь другое решение, которое выглядит лучше?
Записан

- А Вы сами-то верите в привидения?
- Конечно, нет, - ответил лектор и медленно растаял в воздухе.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #1 : 27-07-2007 09:52 » 

Scorp__), да, именно структура - самое подходячее решение в этом случае. Я бы даже сказал - самое удобное , потому автоматически так получится, что она (структура) пригодится вовсе не только в конструкторе.

для "целостности" (если мучает вопрос о "введении новой сущности" Улыбаюсь ) можно описать данную структуру внутри класса твоего объекта. Но, как показывает практика, иногда просто необходимо, чтоб структура было описана вне объекта
« Последнее редактирование: 27-07-2007 09:54 от Алексей1153++ » Записан

Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #2 : 27-07-2007 13:59 » 

Лучше чем структура тоже не знаю.
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Scorp__)
Молодой специалист

ru
Offline Offline
Пол: Мужской

« Ответ #3 : 27-07-2007 18:40 » 

Да, вот так думаешь, что есть какое-то еще сакральное знание, а оказывается, что лучше чем уже делал и сделать нельзя...

А мне до сих пор в это не верится Улыбаюсь
Записан

- А Вы сами-то верите в привидения?
- Конечно, нет, - ответил лектор и медленно растаял в воздухе.
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #4 : 27-07-2007 22:56 » 

ИМХО лучше думать, что существует лучшее решение, чем думать, что найденное решение самое лучшее и окончательное.
Ага Здоровые сомнения ещё ничему никогда не вредили. В противном случае - признаки застоя.

Да и кстати, ставить окончательный крест на доп. ф-ях тоже не следует.

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

Тут всё зависит от определения "вменяемое состояние" и "готов к исполнению". Кто, к примеру, кроме объекта сможет лучше всего определить валидность параметров? Только он сам. А как это сделать в конструкторе?

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

Короче говоря в зависимости от ... оба способа имеют равное право на существование и применение.
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #5 : 28-07-2007 16:59 » 

Я за структурку в качестве параметра.

Джон, Инициализация объекта вне конструктора, через всякие init ИМХО это C, а не C++, если есть ошибки при создании, должно быть исключение.(точка), если конечно НУ ОЧЕНЬ нужно оставить объект в живых после неудачно переданных параметров, то можно и переинициализировать Улыбаюсь помните iostream

пересоздание объекта операция часто очень дешевая это не то место на котором надо экономить, для объектов на стеке еще дешевле.

ИМХО реализуя init люди не явно создают некое подобие синглетона
а синглетон чаше несёт вред чем пользу.
кроме это создание init/reset провоцирует пользователя класса/объекта использовать его там где не надо.
например, есть структура у неё есть конструктор по умолчанию и метод reset делают одно и тоже(конструктор зовёт reset), зачищают какие-то данные
я заполняю эту структруру какимито данными потом отдаю её функции пускай SetSomeFlags, она там что-то делаем с частью данных, что-то меняет, НО какой-то умник решил что он просто обязан внутри функции вызвать reset перед заполнением флагов. Какого спрашивается святого сбросил все данные, кто ему разрешал, где в названии функции указано, что она сбросит все данные, надо было назвать её ResetAndSetSomeFlags.

Я не разу не встречал ситуации, когда ДЕЙСТВИТЕЛЬНО нужно использовать init/reset
это же касается синглетонов.
Записан

Странно всё это....
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #6 : 29-07-2007 09:14 » 

LogRus, мы снова возвращаемся к проблеме широко освещаемой в темах a la "define=зло". Ага

Так и хочется сказать: "Топор".

ДА! Есть такие ситуации, когда конструктор лучше, а init просто недопустима. А есть и наоборот. Причём здесь C или С++?

Примеров - куча. Взять хотябы чтение данных из файла (допустим некой конфигурации). Объект представляет собой элемент списка и должен быть проинициаллизирован данными из файла. Причём файл выбирает пользователь, "errare юзер est" как любили говаривать программеры в древнем Риме.
Он 10 раз подряд выбирает НЕ ТОТ файл (причин приводить не буду их тоже может быть куча). И что? Каждый раз вызывать исключение? Создавать целый механизм исключений (объекты, алгоритм обработки), загромождать код в месте создания объекта именно для данного случая? Хотя, конечно на вкус да на цвет товарищей нет. Ага

Кстати другой пример. Объекты типа "окно". Работают в связке конструктор+Create. Аналог приведённого тобой reset - ф-я Destroy. И что? ЭТо тоже надо реализовать через исключения?
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #7 : 29-07-2007 19:23 » 

Джон, да я так считаю Улыбаюсь

а C ту при том, что это моё мнение Улыбаюсь что так пишут на C? а не на C++ в C++? есть исключения не дающие оверхеда в случае отсутсвия ошибок ну оверхед при ошибках ну так фиг с ним у нас нет цели работать быстро в моменты когда хрупкая реальность летит в тартар. в общем твои примеры не убедительны Улыбаюсь не вижу, где можно загромоздить код.

while (!flag)
{
   try{
     SomeClass someClass(SelectFile());
     flag = true;
   }
   catch(ErrorFile &e)
   {
     ShowMessage(e.what());
   }
}

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

Странно всё это....
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #8 : 30-07-2007 15:59 » 

LogRus, а разве это длинее?

Код:
while (!flag)
{
    SomeClass someClass;

    if (someClass.init(SelectFile()))
        flag = true;
    else
        ShowMessage("error");
}

или более логично

Код:
SomeClass someClass;

while (!someClass.init(SelectFile()))
{
        ShowMessage("error");
}


Главное достоинство try-catch в передаче аргумента. В остальном это громоздко, особенно, если нужно обработать в одном блоке много разных типов ошибок (их еще и описать надо отдельным классом).
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
nikedeforest
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #9 : 30-07-2007 16:24 » 

Это хорошо, ты завел статусную переменную, которая может принимать только два значения. А если у тебя будет не два состояния, а больше?  Преимущество try-catch в том, что эта конструкция позволяет избежать кода большой вложенности (большие совокупности if-else) и не использовать статусных переменных. Т.е. получается, ты при помощи try-catch можешь выделить номинальный код и код обработки ошибки, что более логично и более удобно. Думаю, последний довод не в счет Улыбаюсь.
Хоть как бы сейчас уже принято отходить от программирования в стиле СОМ, но все же местами встречаются предостережения о том, чтобы не использовать повсеместно try-catch, а рассматривать в том числе возможность обработки ошибок с помощью условного оператора. Вот только грань эта размыта, как мне кажется.
Чем-то спор похож на спор по поводу goto Улыбаюсь
Записан

ещё один вопрос ...
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #10 : 30-07-2007 16:31 » 

nikedeforest, точно также:

Код:
MyClass var;
int error;

while((error = var.method()))
{
  switch(error)
  {
    case 1: ....; break;
    case 2: ....; break;
    case 3: ....; break;
    default: ...; break;
   }
}

Дело привычки и стиля. Оба метода имеют право на существование, имеют свои достоинства и недостатки.
« Последнее редактирование: 30-07-2007 16:33 от RXL » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
nikedeforest
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #11 : 30-07-2007 16:36 » 

Длинный свитч - это тоже не есть гуд. НЕ так он удобен, если в нем будет штук 10, а то и более ветвлений.
А я не спорю, что имеют право, вроде выше об этом и  сказал в конце Ага
Записан

ещё один вопрос ...
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #12 : 30-07-2007 16:59 » 

о, кстати. Насчёт try-catch . Тоже часто применяю везде подряд, а тут в соседней теме реализовывал код Хаффмана, там в одном месте идет работа с каждым байтом файла (то есть переходов - хренова туча). Сначала сделал for и вложенный switch, но обломался с выходом из свича и одновременно из for Отлично (на самом деле там всё проще оказалось, но речь вот о чём - )
заменил было на try, и выход при помощи throw 0, оказалось - ТОРМОЗА. для любопытства временно заменил на goto (первый раз за всю практику ))) ) - тормоза ушли. Переделал с for снова (как нужно) - тормозов нету.
Вот так то, злоупотреблять try )
Записан

Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #13 : 30-07-2007 17:59 » 

Алексей1153++, try-catch сам по себе очень тяжеловесный оператор. Так как, там срабатывают механизмы еше и операционной системы при появлении ошибки. Так что не удивительны и тормоза.  Из цикла можно выскочить с помошью оператора break. Хотя сам по себе оператор, как и goto,  также не приветствуется в коде в больших разбавлениях.
« Последнее редактирование: 30-07-2007 18:01 от Finch » Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #14 : 30-07-2007 18:32 » 

Finch,

это всё понятно, у меня было
Код:
for(..;..;..)
{
 ...
 switch(...)
 {
   case ...:
   {
      //отсюда выйти из for
   }
   break;
 }
 ...
}
Записан

Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #15 : 30-07-2007 18:40 » 

Я в такой ситуации использую
Код:
bool flag=true;
int i=0;
while ((i<.....) && flag)
{
.......
switch(...)
 {
   case ...:
   {
      flag=false;
   }
   break;
 }
.......
i++;
}
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #16 : 30-07-2007 19:00 » 

Или еще вариант: условие выхода проверить после switch. Ведь switch может быть не единсвенным оператором в блоке...
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #17 : 30-07-2007 19:08 » new

я присваивал переменной N , которая в условии for(;N;) значение, которое приведёт к выходу из цикла, а в свиче вызывал continue. Но со вложенными циклами такая вещь уже не прокатит )
Записан

RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #18 : 30-07-2007 19:17 » 

В Perl есть возможность указывать, к какому из вложенных циклов применяется оператор через метку цикла. Жаль, что в C/C++ такого не предусмотрели...
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #19 : 30-07-2007 19:23 » 

Ром не слишком часто это и нужно. Второе, при случаи необходимости, это можно эмулировать. Правда я не встречал ситуации, когда мне понадобилось.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Scorp__)
Молодой специалист

ru
Offline Offline
Пол: Мужской

« Ответ #20 : 30-07-2007 19:47 » 

Оп, спор опять перешел не туда Улыбаюсь

Джон, я как раз не отказываюсь от дополнительных функций инициализации. После того как пару раз мне пришлось столкнуться с тем, что мой объект оказался нереентерабелен, я стараюсь везде предоставить функции реинициализации, но желательно разделенные по группам параметров, ну и может быть одну общую, с тем же набором параметров, что у конструктора. Но еще не было случая, чтобы подход конструктор + init был жизненно необходим.

Что касается проверки валидности параметров, так на мой взгляд это прямая задача конструктора. И гораздо лучше проверить параметры еще до выделения памяти и проч. и сообщить пользователю, что сделал-то он что-то не то, чем потом, создав объект, реинициализировать его в случае ошибки. В общем я считаю, что именно конструктор родное место для исключений. Но разбор стилей мы продолжать не будем Улыбаюсь

А вот скажите мне еще, раз уж тема пошла дальше. В процессе работы программы возникает ситуация, когда объект должен быть полностью реинициализирован, то есть возможно даже будет освобождена память из-под каких-то данных (может быть и для всех конструкций объекта) и выделена для нового размера этих данных. Имеет ли право на жизнь такая реинициализация, или лучше тихо-мирно убить объект и сделать новый? Удерживает от такого действия обычно одно: объект асинхронный и что-то там себе выполняет, у приложения есть указатель на него, у объекта есть указатель на событие в приложении, чтобы оповещать его о результатах, все друг друга знают короче и привыкли. А тут вдруг убить и заново знакомиться.

Вот и еще вопрос созрел Улыбаюсь А чем вы обычно пользуетесь для синхронизации разрозненных объектов? Когда один дает другому задание и занимается своими делами, а потом "подрядчик" должен сказать, что он все сделал, ну и разные вариации на эту тему: сообщить что пришла информация, сообщить что закончен обсчет, сообщить что в процессе анализа обнаружено что-то необычное. В общем как на С++ организуется этот самый обмен сообщениями между объектами, который является одной из основ ООП? Улыбаюсь
Записан

- А Вы сами-то верите в привидения?
- Конечно, нет, - ответил лектор и медленно растаял в воздухе.
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #21 : 30-07-2007 20:14 » 

Scorp__), А у тебя что ли объекты работают в разных потоках?
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Scorp__)
Молодой специалист

ru
Offline Offline
Пол: Мужской

« Ответ #22 : 31-07-2007 07:47 » 

Finch, ага. Например захват видео и его обработку на лету в один поток не запихнуть.

Да мне кажется, эта ситуация часто встречается: всякого рода сканеры, например: запущено сканирование, а само приложение должно реагировать на действия пользователя, никак без двух потоков не обойтись.
Записан

- А Вы сами-то верите в привидения?
- Конечно, нет, - ответил лектор и медленно растаял в воздухе.
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #23 : 31-07-2007 18:47 » 

Цитата
Вот и еще вопрос созрел Улыбаюсь А чем вы обычно пользуетесь для синхронизации разрозненных объектов? Когда один дает другому задание и занимается своими делами, а потом "подрядчик" должен сказать, что он все сделал, ну и разные вариации на эту тему: сообщить что пришла информация, сообщить что закончен обсчет, сообщить что в процессе анализа обнаружено что-то необычное. В общем как на С++ организуется этот самый обмен сообщениями между объектами, который является одной из основ ООП? Улыбаюсь
Можно сделать объект, который будет заведовать очередью сообшений. И теперь все посылки будут буфферизироваться до востребования.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #24 : 01-08-2007 05:58 » 

Можно сделать объект, который будет заведовать очередью сообшений. И теперь все посылки будут буфферизироваться до востребования.
можно callback или набор callback(список подписчиков на сообщение)

смотря, что лучше вписывается в архитектуру приложения

кстати offtop
Записан

Странно всё это....
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines