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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Инициализация статических компонентов класса 
V
    Опции темы
SABROG
Дата 19.8.2007, 19:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


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

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



Читаю в книге пример инициализации статического компонента класса

Код

class list
{
public:
static list *begin;
};
...
list *list::begin = NULL;


И вот часть где идет присваивание NULL я никак не могу догнать. Я бы понял такую запись:

Код

list::begin = NULL;


Хоть и не знаю на сколько она правильная. Можете мне разъяснить где тут что к чему относится ?


--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
DjoNIK
Дата 19.8.2007, 19:18 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 320
Регистрация: 28.9.2006
Где: Питер/Георгиевск

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



Первый вариант правильный, и второй тоже (может быть в каком-нибудь другом языке, но не в C++)
Всё очень просто:
Код

list *

говоришь компилятору о том, что инициализируемая переменная будет указателем на list;
Код

list::

говоришь о том, что эта переменная будет членом класса list;
Код

begin = NULL;

собственно задаешь значение переменной.

PS: Что за книгу читаешь?  smile 

Это сообщение отредактировал(а) DjoNIK - 19.8.2007, 19:20


--------------------
- Плесни-ка мне холодного кипятку.
- Как кипяток может быть холодным?! Ты, верно, хочешь кипяченой воды?
- Какая ещё кипяченая вода? Не пудри мне мозги - налейхолодного кипятку.
(разговор петербуржца и москвича)
PM MAIL ICQ   Вверх
SABROG
Дата 19.8.2007, 19:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


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

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



Книжка "Язык С++ В.В. Подбельский 4 издание 1999г.".

Без явного указания типа компилятор ругается:

Код

src\main.cpp:9: error: expected constructor, destructor, or type conversion before '=' token


Это фича такая чтоль или gcc тупит и не может определить тип без явного указания ?

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


--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
DjoNIK
Дата 19.8.2007, 19:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 320
Регистрация: 28.9.2006
Где: Питер/Георгиевск

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



Цитата

Если я правильно понимаю, то часть "list *" - явное указание типа члена класса

Ты правильно понял!
Цитата

несмотря на то, что компилятор и так уже знает какого типа этот член

Действительно, компилятор знает, что у его переменной-члена тип "list *". НО(!) откуда ты думаешь, что компилятор узнает какой именно член класса ты инициализируешь? А ведь для этого  и нужно указать тип(переменная-член)/тип возвращаемого значения(функция-член класса), название класса, поставить двоеточие, указать имя переменной-члена/функции-члена класса и задать значение если это переменная.


--------------------
- Плесни-ка мне холодного кипятку.
- Как кипяток может быть холодным?! Ты, верно, хочешь кипяченой воды?
- Какая ещё кипяченая вода? Не пудри мне мозги - налейхолодного кипятку.
(разговор петербуржца и москвича)
PM MAIL ICQ   Вверх
zkv
Дата 19.8.2007, 20:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата



****


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

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



Цитата(DjoNIK @  19.8.2007,  19:53 Найти цитируемый пост)
компилятор узнает какой именно член класса ты инициализируешь?

а что есть возможность с кем-то перепутать? 
Только типом возвращаемого значения сигнатуры не имеют права отличаться.
PM MAIL   Вверх
DjoNIK
Дата 19.8.2007, 20:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 320
Регистрация: 28.9.2006
Где: Питер/Георгиевск

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



Судя по твоим вопросам, ты не совсем правильно понимаешьсути происходящего. Я сам только начинаю путешествие в этот волшебный мир программирования smile, но смело могу посоветовать перечитать эту книгу более внимательно! Либо как вариант взять более свежее издание, например на Ozon-е сей час лежит пятое(!). И уж как самый крайний вариант прочитать другую книгу, я бы посоветовал Р. Лафоре "Объектно-ориентированное программирование в C++" (сам её дочитываю). Благо в нете полно электронных версий - качай, распечатывай да читай. Но это всё IMHO и  smile 


--------------------
- Плесни-ка мне холодного кипятку.
- Как кипяток может быть холодным?! Ты, верно, хочешь кипяченой воды?
- Какая ещё кипяченая вода? Не пудри мне мозги - налейхолодного кипятку.
(разговор петербуржца и москвича)
PM MAIL ICQ   Вверх
SABROG
Дата 19.8.2007, 20:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


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

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



Ну как же. Если компилятор не позволяет иметь в одном контексте переменную и функцию с одним и тем же именем, а значит по имени четко можно определить переменная это или метод.

Вот что будет если завести метод и переменную с одним именем:

Код

include/TForm.h:113: error: declaration of `void TForm::a()'
include/TForm.h:88: error: conflicts with previous declaration `int TForm::a'
src\main.cpp:9: error: `int TForm::a' is not a static member of `class TForm'



--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
DjoNIK
Дата 19.8.2007, 20:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 320
Регистрация: 28.9.2006
Где: Питер/Георгиевск

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



Цитата(zkv @ 19.8.2007,  20:07)
а что есть возможность с кем-то перепутать?

Вообще-то да, в данном случае не с кем. Но если учесть, что человек будет иметь дело с функциями(о чем ты и говоришь), то здесь тип нужно указать. Но ведь и по семантике одновременного объявления и определения в C++ положено так:
Код

ТИП ИДЕНТИФИКАТОР_ПЕРЕМЕННОЙ = ЗНАЧЕНИЕ;

при условии, что ИДЕНТИФИКАТОР_ПЕРЕМЕННОЙ для членов класса содержит и идентификатор самого класса с разрешением зоны видимости (::).
Или я не прав?


--------------------
- Плесни-ка мне холодного кипятку.
- Как кипяток может быть холодным?! Ты, верно, хочешь кипяченой воды?
- Какая ещё кипяченая вода? Не пудри мне мозги - налейхолодного кипятку.
(разговор петербуржца и москвича)
PM MAIL ICQ   Вверх
bsa
Дата 19.8.2007, 20:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

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



SABROG, привила есть правила. По правилам языка Си, если ты написал:
Код
extern int h;
, то потом ты где-то проекте должен написать:
Код
int h;
Обрати внимание, что тип опять указывается, хоть нельзя 2 раза объявить переменную с одним именем.
Статическая переменная класса в C++ это тоже в некотором роде extern. Только оформлен он немного подругому.
А extern - это не объявление переменной. А декларация того, что она где-то определена. Определение это как раз и есть твой:
Код
list* list::begin = NULL;


Это сообщение отредактировал(а) bsa - 19.8.2007, 20:20
PM   Вверх
SABROG
Дата 19.8.2007, 20:23 (ссылка)    | (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


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

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



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


--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
DjoNIK
Дата 19.8.2007, 20:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 320
Регистрация: 28.9.2006
Где: Питер/Георгиевск

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



Цитата

я могу сделать вывод, что это недоработка стандарта

Весьма сомнительное заявление, т.к. для разбора входной цепочки символов (т.е. исходного файла) используются весьма сложные алгаритмы. Если убрать из стандарта и эту формализацию правил семантики, то они(алгоритмы) станут ещё сложнее, следовательно время компиляции вырастет.
К тому же не так уж и сложно написать пару лишних символов.
Опять же IMHO.

Это сообщение отредактировал(а) DjoNIK - 19.8.2007, 20:32


--------------------
- Плесни-ка мне холодного кипятку.
- Как кипяток может быть холодным?! Ты, верно, хочешь кипяченой воды?
- Какая ещё кипяченая вода? Не пудри мне мозги - налейхолодного кипятку.
(разговор петербуржца и москвича)
PM MAIL ICQ   Вверх
SABROG
Дата 19.8.2007, 20:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


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

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



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

Код

class a
{
public: 
int print(char *);
};
int a::print(char *b)
{
...
return 0;
}


Т.е. информации достаточно, чтобы 1) соотнести метод к конкретному классу 2) выцепить типы параметров
Хотя может я и упускаю, какие-нибудь исключительные ситуации.


--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
DjoNIK
Дата 19.8.2007, 21:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 320
Регистрация: 28.9.2006
Где: Питер/Георгиевск

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



Цитата

везде и повсеместно тип переменных опускается после первого определения

Кстати да! Но ты не забывай, что определение класса - не одно и то же, что определение объекта класса!!!
При определение класса ты как бы сообщаешь компилятору скелет будующих объектов, но ПАМЯТЬ при этом НЕ ВЫДЕЛЯЕТСЯ.
В противовес этому определение объекта выделяет память под уже известный каркас(наш класс). Но если ты определишь объект класса, но забудешь определить статический член класса, то этот член будет содержать случайное значение(в случае объявления локальным) или ноль(если объект глобален).


--------------------
- Плесни-ка мне холодного кипятку.
- Как кипяток может быть холодным?! Ты, верно, хочешь кипяченой воды?
- Какая ещё кипяченая вода? Не пудри мне мозги - налейхолодного кипятку.
(разговор петербуржца и москвича)
PM MAIL ICQ   Вверх
SABROG
Дата 19.8.2007, 21:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


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

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



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

Это сообщение отредактировал(а) SABROG - 19.8.2007, 21:21


--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
DjoNIK
Дата 19.8.2007, 21:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 320
Регистрация: 28.9.2006
Где: Питер/Георгиевск

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



Цитата

компилятор в любом случае проверяет типы

Само собой, но чем более формализована семантика языка, тем лучше для скорости компиляции(кажеться, что я повторяюсь smile ).
Одно дело получить
Код

ТИП ИДЕНТИФИКАТОР_ПЕРЕМЕННОЙ = ЗНАЧЕНИЕ;

и совсем другое
Код

ИДЕНТИФИКАТОР_ПЕРЕМЕННОЙ = ЗНАЧЕНИЕ;


Ну если ты не согласен, то можно аргументировать и отослать в комитет стандартизации до 2009 года  smile .
А вообще-то мы давно отошли от темы топика Господа!


--------------------
- Плесни-ка мне холодного кипятку.
- Как кипяток может быть холодным?! Ты, верно, хочешь кипяченой воды?
- Какая ещё кипяченая вода? Не пудри мне мозги - налейхолодного кипятку.
(разговор петербуржца и москвича)
PM MAIL ICQ   Вверх
SABROG
Дата 19.8.2007, 22:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


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

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



Если я все правильно понял, то причины этого следующие. При определении статического члена необходимо указать его местоположение, если хотите, в памяти, ну или соотнести его принадлежность к определенному блоку/контексту, точно также как это делается при объявлении любой новой переменной, объект на то и статический, что подразумевает то, что место в памяти под него не может быть выделено динамически через оператор new или как статический временный объект внутри любого блока. Таким образом, если объект не может быть создан динамически внутри блока/функции, то он должен быть внешним, вынос местоположения объекта из блока наружу делает объект еще и глобальным. При желании, его можно еще и проинициализировать, но как я понял, делать это совсем не обязательно:

Код

int TForm::a;
    int main(int argc, char *argv[])
    {
    TForm::a = 1;
    }


А вот что бывает, если не указать местоположение статического объекта:

Код

./tmp\main.o(.text+0x144): In function `Z5qMainiPPc':
main.cpp:12: undefined reference to `TForm::a'


Это сообщение отредактировал(а) SABROG - 19.8.2007, 22:49


--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
DjoNIK
Дата 20.8.2007, 08:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 320
Регистрация: 28.9.2006
Где: Питер/Георгиевск

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



Код

int TForm::a;
    int main(int argc, char *argv[])
    {
    TForm::a = 1;
    }

Если ты таким образом инициализируешь статическую переменную a, то в строке 1 она станет равна 0(!), т.к. определена в глобальном пространстве имен. А если ты предпологаешь, что начальное значение должно быть 1, то первая строка должна быть
Код

int TForm::a = 1;

Иначе, по закону Мерфи, кто-нибудь(а может быть и ты сам)  создав экземпляр класса забудет проинициализировать TForm::a еденицей, и будет его использовать с неправильным начальным значением, что может привести к неожиданным результатам.


--------------------
- Плесни-ка мне холодного кипятку.
- Как кипяток может быть холодным?! Ты, верно, хочешь кипяченой воды?
- Какая ещё кипяченая вода? Не пудри мне мозги - налейхолодного кипятку.
(разговор петербуржца и москвича)
PM MAIL ICQ   Вверх
bsa
Дата 20.8.2007, 10:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

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



Цитата(DjoNIK @ 20.8.2007,  08:41)
Код

int TForm::a;
    int main(int argc, char *argv[])
    {
    TForm::a = 1;
    }

Если ты таким образом инициализируешь статическую переменную a, то в строке 1 она станет равна 0(!), т.к. определена в глобальном пространстве имен. А если ты предпологаешь, что начальное значение должно быть 1, то первая строка должна быть
Код

int TForm::a = 1;

Иначе, по закону Мерфи, кто-нибудь(а может быть и ты сам)  создав экземпляр класса забудет проинициализировать TForm::a еденицей, и будет его использовать с неправильным начальным значением, что может привести к неожиданным результатам.

Позволю себе не согласиться с первым утверждением. Значение a на первой строке совсем не обязательно будет равно 0.
PM   Вверх
SABROG
Дата 20.8.2007, 10:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


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

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



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


--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
bsa
Дата 20.8.2007, 10:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

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



Цитата(SABROG @ 20.8.2007,  10:20)
Так и есть. Я хочу лишь показать, что эта конструкция раскладывается на две составляющие - определение и инициализацию, чтобы подтвердить свою догадку о необходимости прописывать тип переменной повторно.

Вобщем да. Определение это list* list::begin; А инициализация - list::begin = NULL;
PM   Вверх
DjoNIK
Дата 20.8.2007, 13:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 320
Регистрация: 28.9.2006
Где: Питер/Георгиевск

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



Цитата

Позволю себе не согласиться с первым утверждением. Значение a на первой строке совсем не обязательно будет равно 0.

Можно конечно и не согласиться, но я отвечал так, как мне было изложенно в теории.
После твоих слов усомнился в своих убеждениях и проверил в MS VC++(2005).
Я всё-таки прав. Переменные определённые, но не проинициализированные в глобальном пространстве имен получают значение по дефолту ноль(ну или NULL для указателей).
Переменные же определённые, но не проинициализированные в локальном пространстве имен получают случайное значение.


--------------------
- Плесни-ка мне холодного кипятку.
- Как кипяток может быть холодным?! Ты, верно, хочешь кипяченой воды?
- Какая ещё кипяченая вода? Не пудри мне мозги - налейхолодного кипятку.
(разговор петербуржца и москвича)
PM MAIL ICQ   Вверх
bsa
Дата 20.8.2007, 14:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

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



Цитата(DjoNIK @ 20.8.2007,  13:29)
Я всё-таки прав. Переменные определённые, но не проинициализированные в глобальном пространстве имен получают значение по дефолту ноль(ну или NULL для указателей).
Переменные же определённые, но не проинициализированные в локальном пространстве имен получают случайное значение.

Это не есть доказательство. Приведи цитату из стандарта.
PM   Вверх
Fazil6
Дата 20.8.2007, 14:19 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Цитата(bsa @  20.8.2007,  14:11 Найти цитируемый пост)
Это не есть доказательство. Приведи цитату из стандарта.


Страуструп. Язык программирования С++. 4.9.5.
Цитата

...
Если инициализатор не задан, то глобальным объектам ($ 4.9.4), объектам из пространства имен ($8.2) и локальным статическим объектам ($ 7.1.2, $10.2.4) (все они называются статическими объектами)  присваивается нулевое значение соответствующего типа...


Добавлено через 1 минуту и 45 секунд
автоматические и динамические объекты не инициализируются поумолчанию
PM MAIL   Вверх
bsa
Дата 20.8.2007, 15:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

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



спасибо. так уже лучше.   smile 
PM   Вверх
Страницы: (2) [Все] 1 2 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
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.0763 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


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

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