Гость
Форумы / C++ [игнор отключен] [закрыт для гостей] / Глобальные объекты в VCL / 10 сообщений из 10, страница 1 из 1
16.07.2021, 00:15
    #40084277
DmitryBykov
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Глобальные объекты в VCL
Здравствуйте.
Вынужден переходить с C# VS на С++ Builder. И возникла такая сложность.

Хочу создать приложение VCL и при этом часть рабочих объектов не привязывать к формам. То есть сделать их не полями класса формы, а глобальными (ну или полями одного глобального объекта). Объекты будут существовать всё время работы приложения.

Делаю примерно так

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
class Tconfig
{
	public:
	int a;
	void Load();
	int GetPar();
};

void Tconfig::Load()
{
	this->a = 10;
}

int Tconfig::GetPar()
{
	return this->a;
}

Tconfig config;

void Init()
{
  config.Load();
}


//---------------------------------------------------------------------------
int WINAPI _tWinMain(HINSTANCE, HINSTANCE, LPTSTR, int)
{
	try
	{
		Application->Initialize();
		Application->MainFormOnTaskBar = true;
		Application->CreateForm(__classid(TForm1), &Form1);

		Init();

                auto aa = config.GetPar(); // aa = 10

		Application->Run();
	}
	catch (Exception &exception)
	{
		Application->ShowException(&exception);
	}
	catch (...)
	{
		try
		{
			throw Exception("");
		}
		catch (Exception &exception)
		{
			Application->ShowException(&exception);
		}
	}
	return 0;
}




Процедура Init должна инициализировать объекты: считывать из файлов конфигурации и заполнять данными. Тут пока всё работает.

Далее пробую использовать объект с формы. Для теста делаю это с таймером.

Код: plaintext
1.
2.
3.
4.
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
	Label1->Caption = std::to_string(config.GetPar()).c_str();
}



И вот тут засада. Label1->Caption выдаёт 0, хотя выше была инициация с a=10. Начинаю отладку и выясняется, что до и после вызова Application->Run() в config разные объекты (разные указатели). То есть за это время С++ пересоздал объект и моя инициация пропала.
Что тут лучше сделать?
Если засунуть Init в FormActivate, то всё работает. Но я не хочу привязываться к форме. Тем более, может получиться, что приложение стартует со скрытой формой. FormCreate и конструктор формы вызываются до Application->Run() .
Быть может можно как-то вызвать код после Application->Run() , но без формы?
Боюсь, что даже если я создам объект параллельного потока для инициализации, то этот объект тоже может не дожить до нужного момента.

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

Кстати, интересная особенность, отладчик всегда отображает первый (правильный) вариант объекта, но данные всё равно выдаются неправильные. И только если запросить указатель объекта, окажется, что указатель-то уже не тот.
...
Рейтинг: 0 / 0
16.07.2021, 00:24
    #40084279
Siemargl
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Глобальные объекты в VCL
DmitryBykov

...
Что тут лучше сделать?
...

1. Выучить С++93.
2. Выучить VCL.

Пример не воспроизводит ошибку.
...
Рейтинг: 0 / 0
16.07.2021, 00:31
    #40084281
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Глобальные объекты в VCL
SiemarglПример не воспроизводит ошибку.

Телепаю: первый кусок кода у него в заголовке.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
16.07.2021, 00:34
    #40084282
White Owl
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Глобальные объекты в VCL
Выносишь определение класса в .hpp файл.
Подключаешь (#include) этот файл в каждый .cpp в котором надо работать с твоим глобальным объектом.
В одном (обычно это main.cpp) делаешь
Код: plaintext
1.
  TConfig config;

Во всех остальных .cpp (или прямо в .hpp с определением класса) делаешь
Код: plaintext
1.
  extern TConfig config;

Инициализацию объекта делаешь при старте приложения (как ты уже сам показал).

Все.

Есть и еще варианты (inline например который обсуждали тут не так давно посмотри старые топики), но работа с extern это классический подход поддерживаемый всеми компиляторами и учебниками, а не только новейшими.
...
Рейтинг: 0 / 0
16.07.2021, 01:08
    #40084285
DmitryBykov
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Глобальные объекты в VCL
Siemargl

1. Выучить С++93.
2. Выучить VCL.


Это понятно. Вот и учу. На практике.

Siemargl

Пример не воспроизводит ошибку.


Возможно по неопытности в С++ я не там ошибку ищу.
Извините, но в С# я привык, что одно объявление объекта даёт один объект, который я сам создаю и уничтожаю. Здесь же это пытаются сделать за меня.

Если я вызываю config->Load из любого события формы (из Activate, Create или конструктора), то всё работает, a = 10.
Если же пытаюсь выполнить config->Load вне формы, в другом файле, то при обращении к объекту в методах (событиях) формы, мне выдают уже другой объект, не инициализированный. И мне трудно понять, почему объявленная единожды переменная имеет разные значения в разном контексте её использования.

как бы получается, что на форму у меня будут идти одни значения, а при вызове объекта откуда-то ещё (допустим, из других потоков) - значения будут уже другие.
...
Рейтинг: 0 / 0
16.07.2021, 01:25
    #40084286
DmitryBykov
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Глобальные объекты в VCL
White Owl,

Спасибо. Не думал как-то что расположение кода как-то влияет.

У меня код-описание располагался в одном из файлов .cpp, а другой на него (на cpp) ссылался в include. И даже не нужный в том коде extern прописан был.

Теперь вынес код в отдельный файл и вроде как один объект остался.
...
Рейтинг: 0 / 0
16.07.2021, 07:05
    #40084290
PetroNotC Sharp
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Глобальные объекты в VCL
DmitryBykov,
По архитектуре.
Ничего страшного если ты будешь создавать объекты по мере надобности.
Преждевременная оптимизация - зло.
...
Рейтинг: 0 / 0
16.07.2021, 10:31
    #40084320
NekZ
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Глобальные объекты в VCL
Пора уже на модули переходить, инклуды для дедов.
...
Рейтинг: 0 / 0
16.07.2021, 10:57
    #40084324
ну я
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Глобальные объекты в VCL
DmitryBykov,

Кажется, тут будет хорошо выглядеть автосоздаваемый DataModule.
...
Рейтинг: 0 / 0
16.07.2021, 12:19
    #40084345
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Глобальные объекты в VCL
NekZПора уже на модули переходить, инклуды для дедов.

То есть ты советуешь аффтару возвращаться на Ц-шарп и не пытаться прыгать выше головы.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Форумы / C++ [игнор отключен] [закрыт для гостей] / Глобальные объекты в VCL / 10 сообщений из 10, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]