2015-04-21 4 views
1

Так что я пишу программу, которая имеет большой класс, называемый oglapp, и целую кучу других классов, использующих его. Я хочу достичь супер-глобального oglapp * во всех моих .cpps. Мой подход заключается в объявлении oglapp * в main.cpp, который имеет точку входа (которая устанавливает указатель и запускает класс), и у меня есть ссылка extern в конце файла заголовка oglapp. Теоретически, если я использую класс oglapp в любом месте моего проекта, мне нужно включить заголовок для него, который включает в себя extern, и я хорош. Это то, что у меня есть:C++ extern pointer

//main.cpp 
oglapp* app; 
entrypoint(){app=new oglapp(); app->run();} 

//oglapp.h 
class oglapp { ... }; extern oglapp* app; 

//classX.h 
#include "oglapp.h" 
classX { ... }; 

//classX.cpp 
#include "classX.h" 
void classX::somefunction(){app->dosomething();} 

То, что я получаю, является большой ошибкой нулевой ссылки. Я попытался включить заголовок oglapp из .cpp класса X, также попытался поместить приложение exgl oglapp *; для каждого из классов в отдельности я пробовал все, что мог придумать. Кроме того, как ни странно, я не получаю нулевые ссылочные ошибки во всех классах. Некоторые из них могут использовать приложение без проблем, некоторые из них видят его как нулевой указатель. Мне еще предстоит выяснить, что определяет, работает оно или нет.

Что я делаю неправильно? Кроме того, если невозможно объявить один суперглобальный указатель на класс таким образом, как мне это сделать?

+0

не существует гарантии, что ваша функция точки входа вызывается в точке, где выполняется некоторый код в ваших файлах классов. Все эти материалы extern действительно не нужны зло –

+0

C++ не имеет «нулевых опорных ошибок». Вы уверены, что не пытаетесь запустить это на Java? : P –

+0

null ссылка или null указатель кто заботится об этом. –

ответ

2

Он будет работать надежно для всего, что было создано изнутри main или что-то, что вызывает main. Для объектов в глобальной области действия они создаются до запуска main, поэтому ваш указатель еще не будет установлен.

Вы можете сделать все инициализированным в пределах main или выше стек вызовов, или вы можете сделать oglapp singleton.

Или, так как он не похож на oglapp принимает никаких аргументов в конструктор, вы можете extern фактический экземпляр и создать один из тех в глобальном масштабе, а не указатель. Тогда вы должны быть осторожны с статическим порядком инициализации фиаско (посмотрите!), Но по крайней мере у ваших других глобальных объектов будет шанс & hellip; если вы будете осторожны.

+0

фактически все вызывается из приложения. точка входа буквально только имеет app = новый oglapp(); app-> Run(); все, что выполняется, вызывается из run(), а при запуске run() указатель уже должен быть установлен – CivDav

+0

Lol, ладно, это что-то не так, только я был глуп и не понимал этого. Я сократил точку входа для приложения = (новый oglapp()) -> run(); и он запустил конструктор, не поместил указатель в приложение, попытался выполнить run(), и я предполагаю, что после этого он поместил бы указатель в приложение, только сбой() был бы разбит. Отделил его как app = new oglapp(); app-> Run(); и работает :) – CivDav

+0

@CivDav: Да: P Почему 'oglapp :: run' не возвращает' void'? –

0

Трудно понять, где проблема, так как вы не разместили весь свой код. Тем не менее, вы можете избежать нулевой справки, сделав oglapp синглом. См. http://en.wikipedia.org/wiki/Singleton_pattern.

+0

К сожалению, я не могу опубликовать весь свой код, потому что это около миллиона строк. Это программа, которую я разрабатывал на некоторое время, я просто реорганизую ее прямо сейчас, и одно из изменений, которые я делаю, - это глобальный oglapp *, вместо того, чтобы хранить один и тот же указатель на одно и то же приложение в каждом из объекты – CivDav

+0

@CivDav, имеет смысл. Также имеет смысл сделать «oglapp» синглтон в этом процессе. –

+0

Я уверен, что вы можете свести его к минимуму в меньшей вещи, которая имеет ту же проблему –

0

«Сингелтон» представляется мне наиболее логичным ответом. И это легко сделать. Вы просто объявляете функцию, которая возвращает экземпляр oglapp ... создавая его в первый раз, возвращая его после этого. Что-то вроде:

static *oglapp _instance = NULL; 
*oglapp oglapp_factory() 
{ 
    if (_instance == NULL) _instance = new oglapp(); 
    return _instance; 
} 

Ваш "Экстерн" файл объявляет как класс четкости и (внешнее существование ...) "oglapp_factory()." Любая процедура, которая должна взаимодействовать с экземпляром класса (один и только), вызывает заводскую процедуру для его получения.