Использование статических членов класса определяемого класса - PullRequest
0 голосов
/ 14 июня 2011

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

foo.h

   class foo
   {
   public:
       virtual ~foo();
   protected:
       foo();
       static foo ms_oFooStaticObject;
   }

foo.cpp

   foo foo::ms_oFooStaticObject;
   foo::foo(){}
   foo::~foo(){}
   void main()
   {
       int i;
   }

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

как это может быть? это ошибка компилятора?

Я использую Visual Studio 2005 (Professional Edition) с пакетом обновления 1 (SP.050727-7600)

Ответы [ 4 ]

4 голосов
/ 14 июня 2011

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

В точке определения ms_oFooStaticObject (в foo.cpp), foo является полным типом, и его конструктор, хотя и protected, доступен для ms_oFooStaticObject.

1 голос
/ 14 июня 2011

@ user797308: Я полагаю, у вас не возникнет проблем, если кто-то объявит и определит глобальную переменную с именем ms_oFooStaticObject. Другими словами, вместо определения foo foo::ms_oFooStaticObject; define foo ms_oFooStaticObject; (Разумеется, это потребовало бы, чтобы конструктор был общедоступным).

Обычные старые ванильные глобальные переменные объявляются через extern <type> <global_name>; и определяются с помощью <type> <global_name>; (возможно, с некоторым начальным значением).

Эти статические члены в классе на самом деле являются просто глобальными переменными с именем класса перед их именами. Определение класса объявляет их. Представьте, что объявление ms_oFooStaticObject внутри класса foo аналогично extern foo ms_oFooStaticObject;. Как насчет определения переменной? Вот что делает foo foo::ms_oFooStaticObject; оператор.

Сравнение с глобалами вполне подходящее. Много багажа связано с глобалами. Хорошая идея - думать о статических членах класса как о тех же проблемах, что и у глобальных в целом.

Редактировать

Ответ Наваза вызвал мысль. Проблема user797308 может заключаться в том, что сам foo::ms_oFooStaticObject защищен, так как его можно определить в области действия файла? Ответ заключается в том, что поскольку язык требует, чтобы эти статические члены данных были определены в области видимости файла, язык, конечно, должен разрешать такие определения, даже для статических членов, которые имеют закрытую видимость.

0 голосов
/ 14 июня 2011

Дай угадаю.Я думаю, что вам интересно, потому что foo сделан protected, и, следовательно, вы думаете, что следующая строка должна выдавать ошибку, поскольку она пытается вызвать непубличный конструктор извне.

foo foo::ms_oFooStaticObject; //definition lies outside the class

Ну, это не правда.ms_oFooStaticObject НЕ является глобальным объектом, хотя поначалу он кажется таким, поскольку его определение находится за пределами класса.

Дело в том, что ms_oFooStaticObject является все еще членом класса, даже если его определение находится за пределами класса.И, как любой член, он может иметь доступ не только к protected членам, но и к private членам:

class A
{
   A() { cout << "constructed" << endl; }  //private constructor
   static A a;                              
};

A A::a;  //okay - member has access to private constructor!
A b;     //error - non-member doesn't has access to private constructtor

Скомпилировать и увидеть сообщение об ошибке вместе с номером строки: http://www.ideone.com/qocH0

Кстати, ваш main() нестандартный, он должен быть одним из следующих:

int main();
int main(int argc, char *argv[]);
0 голосов
/ 14 июня 2011

Конструктор foo::foo() выполнен из-за static определения переменной, которое вы сделали в файле foo.cpp:

foo foo::ms_oFooStaticObject;

Вы вызываете объект class foo.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...