Дать немного коментария по коду

Модераторы: Hawk, Romeo, Absurd, DeeJayC, WinMain

Аватара пользователя
Romeo
Сообщения: 3126
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

По-моему ты невнимательно читаешь. Я же говорю, что это лучше тем, что у меня инициализация производится ОДИН раз, а у тебя ДВА раза. Инициализация должны быть вызвана однократно и только однократно, это вытекает из её определения.

ОК, давай заодно поговорим о проблемах повторной инициализации.

С системными типами данных всё хорошо. Там и в случае инициализации, и в случае присваивания вызывается один и тот же код (грубо говоря memcpy, то есть пересылка данных). Ещё для всех системных типов их деструктор ничего не делает, он пуст. Это ещё более упрощает инициализацию/присваивание.

А вот для классов всё не так. Конструктор по умолчанию (или любой другой конструктор) не должен совпадать по имплементации с оператором присваивания хотя бы потому, что в операторе присваивания должно быть уделено внимание зачистке внутреннего состояния объекта (те же действия, которые выполняются в деструкторе), а лишь потом должна быть произведена пересылка данных. Как следствие, для многих классов повторный вызов конструктора для того же самого объекта не только будет функционировать неожиданно, но вообще приведёт к крашу программы.
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Аватара пользователя
Airhand
Сообщения: 239
Зарегистрирован: 06 окт 2005, 16:21
Откуда: Dnepropetrovsk

В данном, конкретном случае - не класс. И не надо выдумывать, что "если бы" да "кабы" там был класс. Там не класс и при инициализации там нет никакого конструктора.
Оптимизация по скорости:
#define while if
Оптимизация по размеру:
#define struct union
Аватара пользователя
Romeo
Сообщения: 3126
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

Ошибаешься, конструктор есть, и оператор присваивания тоже есть. Более того, есть даже операторы взятия адреса (один константный, другой не константный). То, что ты их не объявлял, это не значит, что их нет. А неправильное их использование исходя только из того, что "так ведь работает", выставляет программиста не с лучшей стороны.

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

Две инициализации быть не должно и точка!
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Аватара пользователя
Airhand
Сообщения: 239
Зарегистрирован: 06 окт 2005, 16:21
Откуда: Dnepropetrovsk

В том конкретном примере, поле является базовым типом. Так что все разговоры про то, что оно может быть классом относятся к категории "если бы да кабы". Да делать инициализацию в наследнике - это даже боле чем "криво". Но также "криво" присваивать в наследнике полю предка. Так что твой вариант ничем не лучше моего.
Оптимизация по скорости:
#define while if
Оптимизация по размеру:
#define struct union
Аватара пользователя
Romeo
Сообщения: 3126
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

Airhand, снова читаешь меня не полностью или не вдумываясь. Где ты в моих постах видишь использование частиц "бы" или "б"?

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

Теперь по поводу того, что оба подхода одинаково кривы. Здесь тоже не соглашусь. Повторное присваивание - норма, повторная инициализация - перманентный нет. Подчёркиваю, я встречался с production кодом, когда подобное присваивание использовалось потому, что иначе никак не сделать. Кстати, чаще всего присваивание поля из базового класса приходится выполнять потому, что в конструкторах нельзя вызывать виртуальные функции, иначе бы это можно было обойти. Но причины - это уже второй вопрос.
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Аватара пользователя
Airhand
Сообщения: 239
Зарегистрирован: 06 окт 2005, 16:21
Откуда: Dnepropetrovsk

Romeo писал(а): Я говорю, что у системных типов есть всё, что есть у классов: конструктор по умолчанию, оператор присваивания, деструктор, операторы взятия адреса.
Это всё есть в c#, а не в с++.
Просто код этих сущностей таков, что повторная инициализация не рушит систему. Написание кода, который работает только потому, что нам повезло - есть признак непрофессионализма.
Где я говорил, что код работает потаму, что нам повезло ? Опять выдумываеш.

Теперь по поводу того, что оба подхода одинаково кривы. Здесь тоже не соглашусь. Повторное присваивание - норма, повторная инициализация - перманентный нет.
Где это норма ? В "кривом" коде - да.
Подчёркиваю, я встречался с production кодом, когда подобное присваивание использовалось потому, что иначе никак не сделать. Кстати, чаще всего присваивание поля из базового класса приходится выполнять потому, что в конструкторах нельзя вызывать виртуальные функции, иначе бы это можно было обойти. Но причины - это уже второй вопрос.
Это нарушает инкапсуляцию. Лучше уж пользоваться так называемыми Set/Get-ами. Приведи пример, где нельзя присвоить в базовом классе.
Оптимизация по скорости:
#define while if
Оптимизация по размеру:
#define struct union
Аватара пользователя
Romeo
Сообщения: 3126
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

&quot писал(а):Это всё есть в c#, а не в с++.
Это всё есть именно в С++, а не в С# (кстати, в последнем языке есть далеко не всё из выше перечисленного, я даже несколько сбит с толку твоим заявлением)
&quot писал(а):Где я говорил, что код работает потаму, что нам повезло ? Опять выдумываеш.
Ты постоянно искажаешь суть сказанного. Ты как раз не говорил, что код работает потому, что нам повезло. Это говорил я! По твоим словам двойная инициализация - это, как раз, гуд. Или нет, не так, это также криво, как и присваивание, хотя это высказывание вообще смешное. Кто нам присваивания (любое количество) запрещает делать? Есть какие-то академически мысли в пользу твоей теории?
&quot писал(а):Где это норма ? В "кривом" коде - да.
Поражаюсь твоему упорству. Ты споришь ради самого процесса?
&quot писал(а):Это нарушает инкапсуляцию. Лучше уж пользоваться так называемыми Set/Get-ами. Приведи пример, где нельзя присвоить в базовом классе.
Погоди, я не говорю, что присваивание лучше setter'а. Более того, я скажу, что setter лучше. Ты снова уходишь в сторону и ищешь новые варианты развития спора, по всей видимости получая от него удовольствие. У нас сейчас идёт эпическое обсуждение intialization vs assignment, а не assignment vs setter. Чувствуешь разницу?

Послушай. Давай начнём с чистого листа. Есть определение инициализации, в котором сказано, что это проставление начального значения для объекта на этапе его создания. Почему ты отрицаешь очевидное: инициализация не может быть проведена дважды?
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Rycharg
Сообщения: 28
Зарегистрирован: 15 апр 2009, 14:23
Откуда: SPb

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

По поводу двойной инициализации...

Код: Выделить всё


class foo{
   protected:
   int  i;
   public:
   foo() : i(0){}
};

class foo2 : public foo{
   public:
   foo2( int x ) : i(x) { }
};
Мой Builder 6 такое не кушает. О чём-то это говорит...
Аватара пользователя
Romeo
Сообщения: 3126
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

&quot писал(а):Мой Builder 6 такое не кушает. О чём-то это говорит...
Совершенно верно, я бы это даже в стандарте запретил :) Однако на данный момент (если не ошибаюсь) этот пункт в стандарте строго не оговорен, и потому некоторые много о себе мнящие компиляторы разрешают это делать, что, порой, приводит к плачевным результатам. Я когда-то с таким сталкивался на AIX 5.1, vacpp compiler (не помню версию). Современные компиляторы, в том числе и AIX 6.1 xlc, не говоря уже о MS VC++, такие попытки пресекают на корню.
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Ответить