Вопрос по c++, constructor – Каковы практические применения защищенного конструктора?

70

Зачем кому-то объявлять конструктор защищенным? Я знаю, что конструкторы объявляются закрытыми, чтобы не допустить их создания в стеке.

Ваш Ответ

7   ответов
3

которые могут его создать, например:

class Level
{
private:

 Level();
 ¨Level();

 friend class LevelManager;
};

Единственный класс, который может создать его экземпляр, это класс LevelManager, поэтому вы всегда будете знать, что экземпляр Level создан в LevelManager.

Хотя это правда, это частный конструктор, не защищенный.
ахаха извините, я прочитал неправильно. Должен ли я удалить свой пост?
87

защищенный конструктор является абсолютно правильным. В этой ситуации вы не хотите, чтобы объекты создавались из класса, а использовали его только для наследования.

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

Канонический способ указать, что класс является абстрактным, - сделать деструктор чисто виртуальным. Но я склонен также защищать конструкторов как для «ремня, так и для подтяжек»; защита и дать понять клиентам, что они не могут напрямую создать экземпляр объекта класса.
Нил, я здесь не веду языковую войну, просто ответил, для чего нужен защищенный ctor. Но вы должны понимать, что существует концепция абстрактного класса на уровне разработки и что она отличается от определения C ++ / Delphi.
Разве недостаточно объявить функцию чисто виртуальной для определения базового класса? Или вышеупомянутое в отсутствии чистой виртуальной функции. Что такое событие создания для производного класса такого абстрактного класса? Amol Gawai
В сочетании с ответами и комментариями этот ответ хорош для меня. Amol Gawai
+1 Но это не обязательно должен быть абстрактный класс. Это часто имеет место, хотя.
6

что только производные члены могут создавать экземпляры класса (и производные экземпляры), используя этот конструктор. Это звучит немного по-детски, но иногда полезно при реализации фабрик классов.

Технически это применимо, только если ВСЕ ctors защищены.
... и использование класса-друга, вызывающего защищенный конструктор, будет в случае объекта, у которого есть члены, которые являются постоянными (устанавливаемыми конструктором), но должны быть общедоступными, но никогда не должны устанавливаться любым другим открытым доступом , гарантирует, что объект не будет создан где-то еще, и поэтому данные также не будут изменены где-либо еще.
Дружественные классы также могут вызывать защищенный конструктор (не только производные классы).
4

который не должен быть доступен для экземпляра напрямую.

9

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

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

5

class mine {

  private:
    mine () {};

  protected:
    mine(int id) : m_id(id) {};

   int m_id;
   static int m_count;

  public:
    static mine* CreateOneOfMe() {
         return mine(m_count++);
    }

    int GetId() { return m_id; }

 };

Это создает экземпляры класса и гарантирует, что каждый из них имеет уникальный инкрементный целочисленный идентификатор. Обратите внимание, что если конструктор, который вы хотите использовать, не является стандартным, вы также должны скрыть стандартный.

Пример кода для выигрыша!
6

ования класса, если ни один из его методов не является чисто виртуальным.

Это не совсем абстрактно в смысле C ++, так как классы-друзья могут использовать его без переопределения, но тогда вам придется объявить их.

Похожие вопросы