Как построить статическую глобальную переменную в C ++ - PullRequest
0 голосов
/ 14 июля 2009

У меня проблемы с компиляцией / связыванием набора классов, некоторые из которых имеют дело с общей глобальной переменной.

По сути, я объявляю и определяю внешнюю переменную foo в классе A и получаю доступ / обновляю ее в классах B и C.

Соответствующий код выглядит так:

А.ч

extern string foo; // declare it <=== compiler error "storage class specified for foo"

B.cpp

include A.h  
string foo; // define it  

main () {   
...  
foo = "abc";      
}  

C.cpp

include A.h  
cout << foo; // print it  

Моя текущая ошибка - "класс хранения, указанный для foo". Но мне интересно, если это правильный подход. Должен ли я использовать статическую переменную? Любая помощь очень ценится, так как я был на этом по крайней мере час к настоящему времени

Ответы [ 8 ]

5 голосов
/ 14 июля 2009

Поскольку ваша ошибка внешняя, я думаю, она не знает, что это за тип.

Вы включили строку?

#include <string>

И если да, то перед ним нужно поставить std:::

#include <string>
extern std::string foo;

Примечание, убедитесь, что вы не используете директивы using (using namespace std или using std::string) в вашем заголовочном файле, потому что тогда вы заставляете всех, кто предъявляет иск на ваш заголовочный файл, делать то же самое, что плохо практика.

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

... но вот как у меня это закодировано.

Вы уверены? Я только что попробовал это, и он прекрасно работает как в VC ++, так и в g ++:

хиджры

#include <string>

extern std::string foo;

B.cpp

#include "A.h"

std::string foo;

int main (void)
{   
    foo = "abc";      
}

C.cpp

#include "A.h"
#include <iostream>

int some_function(void)
{   
    std::cout << foo << std::endl;
}

Попробуйте и посмотрите, работает ли оно.

4 голосов
/ 14 июля 2009

Сделайте это на уровне файлов. Вне основного ()

string foo;

int main () {

}

В противном случае это не глобально, а "auto"

2 голосов
/ 14 июля 2009

В A.h вы действительно получили объявление extern внутри фактического класса A? Ваш вопрос в настоящее время говорит об этом словами, но затем ваш фрагмент кода предполагает, что он находится на уровне файла. Единственный способ получить ошибку, о которой вы говорите, т. Е. «Класс хранения, указанный для foo», заключается в следующем в A.h:

class A
{
public:
    extern std::string foo;
};

Возможно, это ваша проблема?

Редактировать: Глядя на ваш собственный ответ, я думаю, что это то, что вы сделали. Вы хотите заменить extern на static, а затем определить это статическое в A.cpp строкой, подобной

std::string A::foo;

Затем вы можете впоследствии получить к нему доступ в других местах как A::foo например.

std::cout << A::foo;
2 голосов
/ 14 июля 2009

В то время как ответ EFraim является правильным, ваш другой вопрос, является ли это правильным подходом. Ответ: нет, в большинстве случаев.

Наличие единственного глобального значения, которым манипулируют несколько классов, просто напрашивается на проблемы: использование extern довольно тонко. Нет никаких четких советов для любого программиста, смотрящего на ваш код, где определена переменная. Он / она должен сделать полное сканирование источника, чтобы найти его. Также трудно определить, когда какой класс изменяет значение в потоке управления вашего приложения, глобальная переменная связывает разные классы вместе с невидимым бэндом. Хороший дизайн делает сотрудничество между классами явным.

Лучше: сделайте свой глобальный синглтон . Таким образом, вы по крайней мере знаете, где определено значение, и вы можете контролировать изменения значения с помощью методов доступа. Еще лучше: выяснить, почему классы должны иметь доступ к одному и тому же значению, определить, какой класс зависит от того, какой именно аспект, и соответствующим образом пересмотреть свой дизайн. Довольно часто использование extern является просто быстрым решением для более глубокой проблемы проектирования.

1 голос
/ 14 июля 2009

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

Материал, цитируемый в стандарте, не подходит: Джек не пытается определить тип как статический, он пытается создать экземпляр объекта.

Да, вы можете делать только такие вещи, как

class foo {
  // ...
  static int hoo; // class variable same in all instances of foo
  // ...
};

... но это не то, что делает Джек.

Почему весь мой код искажается в этой BBS? На прошлой неделе выложили ответ о C-указателях, и я получил двойные звездочки, когда хотел одиночные!

1 голос
/ 14 июля 2009

Что ж, похоже, что C ++ не позволяет использовать "extern" ни для чего, кроме объектов или функций:

от http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=/com.ibm.xlcpp8a.doc/language/ref/extsc.htm

"C ++ ограничивает использование спецификатора класса хранения extern именами объектов или функций. Использование спецификатора extern с объявлениями типов недопустимо. Объявление extern не может появляться в области видимости класса."

Вернуться к чертежной доске ...

1 голос
/ 14 июля 2009

Кроме перемещения определения за пределы main, убедитесь, что вы включаете заголовок строки перед объявлением extern:

#include <string>
0 голосов
/ 14 июля 2009

Когда вы определяете foo, вы определяете локальную переменную в функции main. Когда вы ссылаетесь, вы получите пропущенный символ, потому что ваш внешний foo; никогда не создается. Вы должны определить foo вне функции.

b.cpp

string foo;
int main () {
   foo = "abc";
}

Еще лучше, вы должны попробовать синглтон.

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