Как ленивым инициировать глобальную переменную?

Я делаю DLL. Я хочу иметь уникальный глобальный var (в моем случае, IBitmap struct), в пространстве имен, для каждого модуля компиляции, который будет включать MyTools.h, Это мой код внутри MyTools.h:

namespace MyTools
{
const IBitmap BITMAP_CONTROL_BACKGROUND;
}

Который инициирует «пустую» переменную. Я хочу инициировать эту переменную, вызывая метод (который возвращает IBitmap) MyClass (который будет создан позже), но когда я делаю это перед каждым процессом, который будет использовать эту переменную:

BITMAP_CONTROL_BACKGROUND = myClass->LoadIBitmap(CONTROL_BACKGROUND, CONTROL_BACKGROUND_PATH, 1);

компилятор скажи мне, что BITMAP_CONTROL_BACKGROUND является const, поэтому я не могу к этому.

Какой (лучший) способ инициализировать позже и сохранить var глобальным?

0

Решение

Прежде всего, позвольте мне сказать вам не делай этого. Вы используете глобальную переменную (с другой для ее инициализации …), тогда это просто Bad ™. Да, вы не хотите делить эту переменную между единицами компиляции, но это делает ее еще более странной (IMO).


Если вы все еще читаете, и я не убедил вас не делать этого, вы можете использовать функцию для инициализации const выражение. Поместите все в свой заголовочный файл:

#pragma once

namespace MyTools {
namespace Impl {
IBitmap InitializeControlBackground();
}

const IBitmap BITMAP_CONTROL_BACKGROUND(Impl::InitializeControlBackground());
}

IBitmap MyTools::Imp::InitializeControlBackground() {
return myClass->LoadIBitmap(CONTROL_BACKGROUND, CONTROL_BACKGROUND_PATH, 1);
}

Несколько заметок:

  • InitializeControlBackground() объявлен во вложенной реализации Impl пространство имен, чтобы не загрязнять MyTools Пространство имен.
  • Если InitializeControlBackground() может отличаться для каждого модуля компиляции, а затем просто переместить его в .cpp вместо .h.
1

Другие решения

Здесь можно использовать случайный синглтон, но вам нужно предоставить объект фабрики для инициализации экземпляра. Если вы можете создать myClass в любой момент:

// Header file.
namespace MyTools
{
const IBitmap * bitmapControlBackground();
}

// Source file.
const IBitmap * MyTools::bitmapControlBackground()
{
// Here is a casual singleton. If multi-thread access is possible,
// here must be a casual way to solve it with mutex.
static const IBitmap instance = MyClass().LoadBitmap(...);
return &instance;
}

Если у вас есть глобальный myClass переменная:

// Source file.
const IBitmap * MyTools::bitmapControlBackground()
{
// Here is a casual singleton. If multi-thread access is possible,
// here must be a casual way to solve it with mutex.
static const IBitmap instance = myClass->LoadBitmap(...);
return &instance;
}

В противном случае вы должны передать его при каждом вызове:

// Header file.
namespace MyTools
{
const IBitmap * bitmapControlBackground(MyClass *creator);
}

// Source file.
const IBitmap * MyTools::bitmapControlBackground(MyClass *creator)
{
// Here is a casual singleton. If multi-thread access is possible,
// here must be a casual way to solve it with mutex.
static const IBitmap instance = creator->LoadBitmap(...);
return &instance;
}
1

По вопросам рекламы [email protected]