2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




Начать новую тему Ответить на тему
 
 C++: static-атрибуты класса - почему так?
Сообщение01.12.2011, 16:10 


14/08/09
9
Москва
Давно пишу на плюсах, но как-то не приходилось пользоваться статическими атрибутами. Недавно же такая необходимость возникла. Недолго думая, написал код вида:
Код:
class C
{
  public:
    C();
    ~C();
  private:
    static string s;
};

на что VC++ выдал мне link error следующего содержания:
Код:
1>C.obj : error LNK2001: unresolved external symbol "private: static class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > C::s" (?s@C@@0V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@A)

Заглянув в справочник Шилдта, обнаружил, что статический атрибут недостаточно объявить в описании класса и что правильно писать так:
Код:
class C
{
  public:
    C();
    ~C();
  private:
    static string s;
};

string C::s;

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

 Профиль  
                  
 
 Re: C++: static-атрибуты класса - почему так?
Сообщение01.12.2011, 16:21 
Аватара пользователя


25/07/11
54
Киев
Начнем с того, что
Код:
string C::s;


не объявление, а определение...

 Профиль  
                  
 
 Re: C++: static-атрибуты класса - почему так?
Сообщение01.12.2011, 16:33 


14/08/09
9
Москва
kiyanyn
ОК, согласен. Но ведь методы можно определять прямо в описании класса. Почему не разрешается делать это с атрибутами? Причём не со всеми, а именно со статическими?

 Профиль  
                  
 
 Re: C++: static-атрибуты класса - почему так?
Сообщение01.12.2011, 17:42 
Аватара пользователя


25/07/11
54
Киев
aUruM в сообщении #510446 писал(а):
kiyanyn
ОК, согласен. Но ведь методы можно определять прямо в описании класса. Почему не разрешается делать это с атрибутами? Причём не со всеми, а именно со статическими?


Встречный вопрос - и как вы определите не статический член? Он создается только при создании объекта, до того его нет, так что это не определение, а объявление...

А что касается определения статического члена класса - то как, например, в общем случае разрешать конфликт имен?

 Профиль  
                  
 
 Re: C++: static-атрибуты класса - почему так?
Сообщение01.12.2011, 17:48 
Заслуженный участник


04/05/09
4587
Статические данные класса по сути - глобальные переменные с видимостью в namespace класса. Соответственно, на них налагаются те же требования, что и на обычные глобальные переменные, в том числе определение только в одном модуле компиляции. Иначе трудно будет реализовать единственность и однократное конструирование такого объекта.

 Профиль  
                  
 
 Re: C++: static-атрибуты класса - почему так?
Сообщение01.12.2011, 23:04 


14/08/09
9
Москва
Цитата:
Встречный вопрос - и как вы определите не статический член? Он создается только при создании объекта, до того его нет, так что это не определение, а объявление...

Согласен, про не-static атрибуты я сказал ерунду. Не подумал.
Цитата:
А что касается определения статического члена класса - то как, например, в общем случае разрешать конфликт имен?

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

Что-то я не очень понимаю, как это соотносится с моим вопросом... Прошу прощения, если туплю. Можете подробнее объяснить? Суть моего вопроса такова: почему компилятору недостаточно строки
Код:
static string s;

в описании класса?

 Профиль  
                  
 
 Re: C++: static-атрибуты класса - почему так?
Сообщение01.12.2011, 23:25 
Заслуженный участник


04/05/09
4587
Потому что компилятору надо ровно в одном объектном файле завести эту переменную с конструированием. Чтобы указать ему в каком именно файле это делать, вы пишете в одном из исходных файлов (не заголовке) определение этой переменной.

 Профиль  
                  
 
 Re: C++: static-атрибуты класса - почему так?
Сообщение01.12.2011, 23:49 


14/08/09
9
Москва
venco
Хм, это объяснение выглядит логичным. Но почему же тогда допускается реализация методов в заголовке?

 Профиль  
                  
 
 Re: C++: static-атрибуты класса - почему так?
Сообщение02.12.2011, 00:32 
Заслуженный участник


04/05/09
4587
aUruM в сообщении #510665 писал(а):
venco
Хм, это объяснение выглядит логичным. Но почему же тогда допускается реализация методов в заголовке?
Потому что inline методам не обязательно быть в одном экземпляре. Более того, часто этого метода в явном виде вообще нет в скомпилированной программе.

 Профиль  
                  
 
 Re: C++: static-атрибуты класса - почему так?
Сообщение02.12.2011, 00:40 


14/08/09
9
Москва
venco
Ясно, спасибо за разъяснение!
Цитата:
Более того, часто этого метода в явном виде вообще нет в скомпилированной программе.

Не могли бы Вы рассказать подробнее про это, если не сложно, или дать ссылку? Интересно.

 Профиль  
                  
 
 Re: C++: static-атрибуты класса - почему так?
Сообщение02.12.2011, 01:02 
Заслуженный участник


04/05/09
4587
При вызове inline функции (не только в классе) при возможности компилятор вставляет код этой функции прямо в вызывающий. Это позволяет лучше соптимизировать код, и избежать кода сопутствующего вызову функции - сохранение параметров и регистров в стек, собственно вызов, коррекция stackframe, и т.д.

 Профиль  
                  
 
 Re: C++: static-атрибуты класса - почему так?
Сообщение02.12.2011, 01:07 


14/08/09
9
Москва
venco
Спасибо!

 Профиль  
                  
 
 Re: C++: static-атрибуты класса - почему так?
Сообщение02.12.2011, 02:33 
Заслуженный участник


26/07/09
1559
Алматы
2aUruM
Цитата:
Но я вот задался вопросом: а для чего это было сделано, зачем повторно объявлять атрибут, который уже был объявлен в описании класса?

Можно ещё совсем упрощенно объяснить -- выделение памяти под обычный элемент класса, например "поле" field в классе struct myclass {int field;};, происходит когда мы объявляем переменную-объект этого класса (e.g. myclass myobject;) или создаем этот объект оператором new.

Но если мы объявим field как static, т.е. напишем struct myclass {static int field;};, этот элемент должен быть доступен даже просто как myclass::field, причем вообще без необходимости создания объекта класса. Спрашивается, а где-же тогда выделяется память под такую переменную? Вот именно это лишнее определение static int myclass::field; вне класса и решает эту проблему.

Цитата:
Может быть, это связано с какими-то ограничениями старых компиляторов?

Хм, интересная мысль. Я слышал, что некоторые компиляторы действительно позволяют обходится единственным определением (с инициализацией) static-элемента в пределах определения класса. Наверное что-то вроде struct myclass {static const int field=2;};, но это не совсем по стандарту и при необходимости должно быть заменено тем же enum'ом. Как с этим дела обстоят в новом C++11 -- пока не знаю.

Кстати, коль скоро static-методы в отличии от static-данных не требуют дублирования описания, вместо таких переменных класса можно попробовать использовать методы. Например struct myclass {static int field(){return 2;}}; :)

Ok, необходимость повторного описания static-переменных выглядит как техническое ограничение. Но можно привести простой пример, демонстрирующий существенность такого поведения. Скажем, есть класс в заголовке. Он используется в другом сpp-файле. Как должен был бы действовать компилятор, чтобы обойтись одним определением static-переменной в самом классе? Трудно сказать. Ведь этот заголовок может использоваться многими файлами, и, неявно, память должна была бы выделяться либо в одном из них (в каком?), либо в каждом из них, что в свою очередь, очевидно, может нарушить требование единственности static-переменной и одинаковости её значения для всех объектов класса и без использования оных.

 Профиль  
                  
 
 Re: C++: static-атрибуты класса - почему так?
Сообщение02.12.2011, 10:08 
Аватара пользователя


25/07/11
54
Киев
В принципе, чисто теоретически можно пойти и на такое :), но разрешение конфликта будет ужасным...

Например:

s.h:
Код:
class Test
{
public:
    static char * s;
};


s1.cpp:
Код:
#include "s.h"
char * Test::s = __FILE__;


s2.cpp:
Код:
#include "s.h"
char * Test::s = __FILE__;


s3.cpp:
Код:
#include "s.h"
#include <stdio.h>
int main()
{
    printf("%s\n",Test::s);
}


Компилируем, получаем предупреждение о redefinition... Программа работает, но этого ли мы хотели? :-)

Вот примерно то же получится и в случае определения статического члена в объявлении класса...

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 14 ] 

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group