Инициализировать статический член внутри конструктора экземпляра

Я хочу инициализировать статическую переменную-член внутри конструктора конкретного экземпляра. Это плохая идея?

Ситуация следующая. У меня есть статическая переменная-член, которую должны использовать все экземпляры этого класса. Обычно я бы просто использовал статический инициализатор. Но у меня нет необходимой информации, необходимой для создания статического объекта, пока не будет вызван конструктор. Но, конечно, я не хочу создавать новый объект каждый раз, когда вызывается конструктор, поэтому я хочу сделать что-то подобное.

class Foo
{
    static Bar * bar;
    Foo( Xyz xyz);
};

Bar * Foo::bar = nullptr;

Foo::Foo(Xyz xyz)
{
    if (Foo::bar == nullptr)
    {
         // initialize static bar 
         Foo::bar = new Bar(xyz);
    }
}

Я знаю конечно xyz Миг должен быть разным для разных обращений к конструктору Foo, Это не имеет значения для меня.

Это плохой дизайн программного обеспечения? Я чувствую себя немного странно при инициализации статического объекта внутри конструктора. Но это ничем не отличается от шаблона проектирования синглтона. Так может это нормально?

РЕДАКТИРОВАТЬ

Спасибо за комментарии, ребята. Кажется, что люди не являются поклонниками этого дизайна. Я изменю это так, чтобы я создал Bar один раз до самого первого экземпляра Fooи передать Bar * в качестве параметра в Fooконструктор. каждый Foo будет иметь указатель на Barи я позабочусь обо всех Fooвсе указывают на одно и то же Bar, Это лучше?

1 ответ

Это плохой дизайн программного обеспечения?

В общем, это было бы так, да. Есть много причин, по которым шаблон Singleton Pattern или наличие статических переменных таким образом считается плохим дизайном.


Но это ничем не отличается от шаблона проектирования синглтона. Так может это нормально?

Если вы действительно хотите создать этот синглтон-паттерн, вам лучше использовать технику Скотта Мейера:

class Foo
{
    static Bar* bar(Xyz xyz) {
        static Bar barInstance(xyz);
        return &barInstance;
    }
    Foo( Xyz xyz) : xyz_(xyz) {}

    void baz() {
        Bar* b = bar(xyz_);
        // use b ...
    }

private:
    Xyz xyz_;
};

Этот код будет потокобезопасным и избавит от необходимости проверять наличие nullptr,


Хоть Bar должен составить синглтон сам по себе, и вы используете его в Foo при необходимости:

class Bar {
public:
    static Bar& getInstance(Xyz xyz) {
        static Bar barInstance(xyz);
        return &barInstance;
    }

private:
    Bar(Xyz xyz) : xyz_(Xyz) {}
    Bar(const Bar&) delete;
    Bar(Bar&&) delete;
    Bar& operator=(const Bar&) delete;
    Bar& operator=(Bar&) delete;

    Xyz xyz_;
};

class Foo {
public:
    Foo(Xyz xyz) barRef(Bar::getInstance(xyz)) {
                                      // ^^^ Notice 1st instance of Foo created
                                      //     wins to create the Bar actually
    }
private:
    Bar& barRef;
};
Другие вопросы по тегам