| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Общие вопросы > Инициализация статических компонентов класса |
| Автор: SABROG 19.8.2007, 19:08 | ||||
Читаю в книге пример инициализации статического компонента класса
И вот часть где идет присваивание NULL я никак не могу догнать. Я бы понял такую запись:
Хоть и не знаю на сколько она правильная. Можете мне разъяснить где тут что к чему относится ? |
| Автор: DjoNIK 19.8.2007, 19:18 | ||||||
| Первый вариант правильный, и второй тоже (может быть в каком-нибудь другом языке, но не в C++) Всё очень просто:
говоришь компилятору о том, что инициализируемая переменная будет указателем на list;
говоришь о том, что эта переменная будет членом класса list;
собственно задаешь значение переменной. PS: Что за книгу читаешь? |
| Автор: SABROG 19.8.2007, 19:36 | ||
| Книжка "Язык С++ В.В. Подбельский 4 издание 1999г.". Без явного указания типа компилятор ругается:
Это фича такая чтоль или gcc тупит и не может определить тип без явного указания ? |
| Автор: DjoNIK 19.8.2007, 19:53 | ||||
Ты правильно понял!
Действительно, компилятор знает, что у его переменной-члена тип "list *". НО(!) откуда ты думаешь, что компилятор узнает какой именно член класса ты инициализируешь? А ведь для этого и нужно указать тип(переменная-член)/тип возвращаемого значения(функция-член класса), название класса, поставить двоеточие, указать имя переменной-члена/функции-члена класса и задать значение если это переменная. |
| Автор: zkv 19.8.2007, 20:07 |
а что есть возможность с кем-то перепутать? Только типом возвращаемого значения сигнатуры не имеют права отличаться. |
| Автор: DjoNIK 19.8.2007, 20:08 |
| Судя по твоим вопросам, ты не совсем правильно понимаешьсути происходящего. Я сам только начинаю путешествие в этот волшебный мир программирования |
| Автор: SABROG 19.8.2007, 20:11 | ||
| Ну как же. Если компилятор не позволяет иметь в одном контексте переменную и функцию с одним и тем же именем, а значит по имени четко можно определить переменная это или метод. Вот что будет если завести метод и переменную с одним именем:
|
| Автор: DjoNIK 19.8.2007, 20:17 | ||||
Вообще-то да, в данном случае не с кем. Но если учесть, что человек будет иметь дело с функциями(о чем ты и говоришь), то здесь тип нужно указать. Но ведь и по семантике одновременного объявления и определения в C++ положено так:
при условии, что ИДЕНТИФИКАТОР_ПЕРЕМЕННОЙ для членов класса содержит и идентификатор самого класса с разрешением зоны видимости (::). Или я не прав? |
| Автор: bsa 19.8.2007, 20:18 | ||||||
SABROG, привила есть правила. По правилам языка Си, если ты написал:
Статическая переменная класса в C++ это тоже в некотором роде extern. Только оформлен он немного подругому. А extern - это не объявление переменной. А декларация того, что она где-то определена. Определение это как раз и есть твой:
|
| Автор: SABROG 19.8.2007, 20:23 |
| Ну если больше аргументов нет, то я могу сделать вывод, что это недоработка стандарта, т.к. реальной пользы от соблюдения этого правила нет, только путаница. |
| Автор: DjoNIK 19.8.2007, 20:30 | ||
Весьма сомнительное заявление, т.к. для разбора входной цепочки символов (т.е. исходного файла) используются весьма сложные алгаритмы. Если убрать из стандарта и эту формализацию правил семантики, то они(алгоритмы) станут ещё сложнее, следовательно время компиляции вырастет. К тому же не так уж и сложно написать пару лишних символов. Опять же IMHO. |
| Автор: SABROG 19.8.2007, 20:40 | ||
И все же, мне кажется, дело вовсе не в скорости, т.к. везде и повсеместно тип переменных опускается после первого определения. Или вот я не могу понять почему необходимо писать прототипы функций/определения, если их прототипы дублируются в реализации:
Т.е. информации достаточно, чтобы 1) соотнести метод к конкретному классу 2) выцепить типы параметров Хотя может я и упускаю, какие-нибудь исключительные ситуации. |
| Автор: DjoNIK 19.8.2007, 21:12 | ||
Кстати да! Но ты не забывай, что определение класса - не одно и то же, что определение объекта класса!!! При определение класса ты как бы сообщаешь компилятору скелет будующих объектов, но ПАМЯТЬ при этом НЕ ВЫДЕЛЯЕТСЯ. В противовес этому определение объекта выделяет память под уже известный каркас(наш класс). Но если ты определишь объект класса, но забудешь определить статический член класса, то этот член будет содержать случайное значение(в случае объявления локальным) или ноль(если объект глобален). |
| Автор: SABROG 19.8.2007, 21:18 |
| Да, только на эту ситуацию наличие или отсутствие типа статического члена класса, за пределами этого класса никак не влияет. Прописав явную инициализацию объекта, еще и указав какому классу он принадлежит компилятор знает чего и сколько вешать в граммах, причем на скорость компиляции это влияет в любом случае, т.к. происходит сравнение типов, я уже попробовал вместо int напсать unsigned int и получил ошибочку, т.е. компилятор в любом случае проверяет типы. |
| Автор: DjoNIK 19.8.2007, 21:34 | ||||||
Само собой, но чем более формализована семантика языка, тем лучше для скорости компиляции(кажеться, что я повторяюсь Одно дело получить
и совсем другое
Ну если ты не согласен, то можно аргументировать и отослать в комитет стандартизации до 2009 года А вообще-то мы давно отошли от темы топика Господа! |
| Автор: SABROG 19.8.2007, 22:38 | ||||
Если я все правильно понял, то причины этого следующие. При определении статического члена необходимо указать его местоположение, если хотите, в памяти, ну или соотнести его принадлежность к определенному блоку/контексту, точно также как это делается при объявлении любой новой переменной, объект на то и статический, что подразумевает то, что место в памяти под него не может быть выделено динамически через оператор new или как статический временный объект внутри любого блока. Таким образом, если объект не может быть создан динамически внутри блока/функции, то он должен быть внешним, вынос местоположения объекта из блока наружу делает объект еще и глобальным. При желании, его можно еще и проинициализировать, но как я понял, делать это совсем не обязательно:
А вот что бывает, если не указать местоположение статического объекта:
|
| Автор: DjoNIK 20.8.2007, 08:41 | ||||
Если ты таким образом инициализируешь статическую переменную a, то в строке 1 она станет равна 0(!), т.к. определена в глобальном пространстве имен. А если ты предпологаешь, что начальное значение должно быть 1, то первая строка должна быть
Иначе, по закону Мерфи, кто-нибудь(а может быть и ты сам) создав экземпляр класса забудет проинициализировать TForm::a еденицей, и будет его использовать с неправильным начальным значением, что может привести к неожиданным результатам. |
| Автор: bsa 20.8.2007, 10:10 | ||||||
Позволю себе не согласиться с первым утверждением. Значение a на первой строке совсем не обязательно будет равно 0. |
| Автор: SABROG 20.8.2007, 10:20 |
| Так и есть. Я хочу лишь показать, что эта конструкция раскладывается на две составляющие - определение и инициализацию, чтобы подтвердить свою догадку о необходимости прописывать тип переменной повторно. |
| Автор: bsa 20.8.2007, 10:42 | ||
Вобщем да. Определение это list* list::begin; А инициализация - list::begin = NULL; |
| Автор: DjoNIK 20.8.2007, 13:29 | ||
Можно конечно и не согласиться, но я отвечал так, как мне было изложенно в теории. После твоих слов усомнился в своих убеждениях и проверил в MS VC++(2005). Я всё-таки прав. Переменные определённые, но не проинициализированные в глобальном пространстве имен получают значение по дефолту ноль(ну или NULL для указателей). Переменные же определённые, но не проинициализированные в локальном пространстве имен получают случайное значение. |
| Автор: bsa 20.8.2007, 14:11 | ||
Это не есть доказательство. Приведи цитату из стандарта. |
| Автор: Fazil6 20.8.2007, 14:19 | ||
Страуструп. Язык программирования С++. 4.9.5.
Добавлено через 1 минуту и 45 секунд автоматические и динамические объекты не инициализируются поумолчанию |
| Автор: bsa 20.8.2007, 15:51 |
| спасибо. так уже лучше. |