Как создать один экземпляр базового класса - PullRequest
0 голосов
/ 28 ноября 2018

У меня есть класс GenericRoot, который имеет ряд классов, которые происходят от него.Я хотел бы создать только один экземпляр этого класса.Я знаком с этим подходом, который я видел здесь :

    class genericRoot {
    private:
        genericRoot() {}

    public:
        static genericRoot &getInstance ();
    };

class Handler : public genericRoot {
}

Однако это приводит к тому, что каждый обработчик (и каждый другой класс, который происходит от общего корня), получает две ошибки:

"ошибка: в этом контексте"

"ошибка: genericRoot :: genericRoot является частной"

Есть ли чистый способ сделать это?

Ответы [ 3 ]

0 голосов
/ 28 ноября 2018

Краткий ответ: нет.Смысл создания приватного конструктора genericRoot состоит в том, чтобы предотвратить его создание в любом месте, кроме метода фабрики getInstance.Когда вы создаете экземпляр подкласса genericRoot, вы неявно создаете также экземпляр genericRoot.(Фактически, новый объект равен a genericRoot, пока работает конструктор genericRoot.)

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

class genericRoot
{
private:
  static SomeType private_state_;
protected:
  // whatever state accessors are needed for subclasses...
};

Вместо конструктора для genericRoot вы просто инициализируете приватное состояние внутри соответствующего файла cpp:

SomeType genericRoot::private_state_ = InitializePrivateState();
0 голосов
/ 28 ноября 2018

Если вам действительно нужно создать подкласс genericRoot, оставив конструктор genericRoot закрытым, вы можете объявить каждый подкласс friend следующим образом:

class genericRoot {
private:
    genericRoot() {}
    friend class Handler;

public:
    static genericRoot &getInstance();
};

class Handler : public genericRoot {
};

Iоднако согласитесь с другими ответами, которые вам следует тщательно продумать, почему / действительно ли вам нужны подклассы одноэлементного класса, поскольку это довольно странная ситуация.

0 голосов
/ 28 ноября 2018

Есть ли чистый способ сделать это?

Конечно.Сделайте конструктор по умолчанию для genericRoot a protected функции-члена.

class genericRoot {
  protected:
    genericRoot() {}

  public:
    static genericRoot &getInstance ();
};

Сказав это, я хочу предупредить вас, что потребность в объекте базового класса не звучит правильно.Это признак ошибки дизайна где-то.Немного подумайте о своих требованиях и выясните, есть ли способ удовлетворить требования, не создавая экземпляр базового класса.

...