Какая польза от создания конструктора в classе?

Почему мы должны сделать конструктор закрытым в classе? Поскольку нам всегда нужен конструктор, который будет публичным.

Некоторые причины, по которым вам может понадобиться частный конструктор:

  1. К конструктору можно получить доступ только из статического заводского метода внутри самого classа. Singleton также может принадлежать этой категории.
  2. Класс полезности , который содержит только статические методы.

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

A. Ваши экземпляры classов создаются static методом. static метод объявляется как public .

 class MyClass() { private: MyClass() { } public: static MyClass * CreateInstance() { return new MyClass(); } }; 

B. Ваш class – одноэлементный . Это означает, что в программе существует не более одного экземпляра вашего classа.

 class MyClass() { private: MyClass() { } public: MyClass & Instance() { static MyClass * aGlobalInst = new MyClass(); return *aGlobalInst; } }; 

C. (применяется только к предстоящему стандарту C ++ 0x) У вас есть несколько конструкторов. Некоторые из них объявлены public , другие – private . Для уменьшения размера кода публичные конструкторы «вызывают» частные конструкторы, которые, в свою очередь, выполняют всю работу. Таким образом, ваши public конструкторы называются делегирующими конструкторами:

 class MyClass { public: MyClass() : MyClass(2010, 1, 1) { } private: MyClass(int theYear, int theMonth, int theDay) { /* do real work */ } }; 

D. Вы хотите ограничить копирование объектов (например, из-за использования общего ресурса):

 class MyClass { SharedResource * myResource; private: MyClass(const MyClass & theOriginal) { } }; 

E. Ваш class – это class полезности . Это означает, что он содержит только static элементы. В этом случае экземпляр объекта никогда не должен создаваться в программе.

Чтобы оставить «заднюю дверь», которая позволяет другому classу / функции друга строить объект таким образом, который запрещен пользователю. Примером, который приходит на ум, является контейнер, создающий iterator (C ++):

 Iterator Container::begin() { return Iterator(this->beginPtr_); } // Iterator(pointer_type p) constructor is private, // and Container is a friend of Iterator. 

Все застряли на Синглтон, ничего себе.

Другие вещи:

  • Остановить людей от создания вашего classа в стеке; создавать частные конструкторы и только ручные указатели по заводскому методу.
  • Предотrotation создания копий classа (частный конструктор копирования)

Это может быть очень полезно для конструктора, который содержит общий код; частные конструкторы могут быть вызваны другими конструкторами, используя «this (…);» нотации. Сделав общий код инициализации в частном (или защищенном) конструкторе, вы также четко укажете, что он вызывается только во время построения, что не так, если это просто метод:

 public class Point { public Point() { this(0,0); // call common constructor } private Point(int x,int y) { m_x = x; m_y = y; } }; 

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

Если вы пишете сборку, используемую третьими сторонами, может быть несколько внутренних classов, которые вы хотите создать только своей сборкой, а не быть созданными пользователями вашей сборки.

Это гарантирует, что вы (class с частным конструктором) управляете вызовом конструктора.

Пример. Статический заводский метод в classе может возвращать объекты по мере того, как заводский метод хочет их распределить (например, например, на фабрике singleton).

У нас также может быть частный конструктор, который должен быть создан только для определенного classа (по соображениям безопасности).

Один из способов сделать это – это иметь class друзей.

Пример C ++:

 class ClientClass; class SecureClass { private: SecureClass(); // Constructor is private. friend class ClientClass; // All methods in //ClientClass have access to private // & protected methods of SecureClass. }; class ClientClass { public: ClientClass(); SecureClass* CreateSecureClass() { return (new SecureClass()); // we can access // constructor of // SecureClass as // ClientClass is friend // of SecureClass. } }; 

Примечание. Примечание. Только ClientClass (поскольку он является другом SecureClass) может вызвать конструктор SecureClass.

Если он частный, то вы не можете его назвать ==> вы не можете создать экземпляр classа. Полезен в некоторых случаях, как одиночный.

Здесь есть обсуждение и еще несколько примеров.

Я видел, как вы решали тот же вопрос.

Просто если вы не хотите разрешать другим создавать экземпляры, то сохраняйте constuctor в пределах ограниченного объема. Практическое приложение (пример) – это одноэлементный шаблон.

Вы не должны закрывать конструктор. Период. Сделайте его защищенным, поэтому вы можете расширить class, если вам нужно.

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

Если это class утилиты, более простое, правильное и более элегантное решение состоит в том, чтобы пометить весь class «статический окончательный», чтобы предотвратить расширение. Не имеет никакого значения просто отметить конструктор закрытым; действительно определенный пользователь всегда может использовать reflection для получения конструктора.

Допустимое использование:

  • Одним из полезных способов использования protected конструктора является принудительное использование статических заводских методов, которые позволяют вам ограничить создание экземпляра или пул и повторно использовать дорогостоящие ресурсы (соединения БД, собственные ресурсы).
  • Синглтоны (обычно это не хорошая практика, но иногда необходимо)

Конструктор является приватным для определенной цели, например, когда вам нужно реализовать singleton или ограничить количество объектов classа. Например, в реализации singleton мы должны сделать конструктор частным

 #include using namespace std; class singletonClass { static int i; static singletonClass* instance; public: static singletonClass* createInstance() { if(i==0) { instance =new singletonClass; i=1; } return instance; } void test() { cout<<"successfully created instance"; } }; int singletonClass::i=0; singletonClass* singletonClass::instance=NULL; int main() { singletonClass *temp=singletonClass::createInstance();//////return instance!!! temp->test(); } 

Опять же, если вы хотите ограничить создание объекта до 10, используйте следующие

 #include using namespace std; class singletonClass { static int i; static singletonClass* instance; public: static singletonClass* createInstance() { if(i<10) { instance =new singletonClass; i++; cout<<"created"; } return instance; } }; int singletonClass::i=0; singletonClass* singletonClass::instance=NULL; int main() { singletonClass *temp=singletonClass::createInstance();//return an instance singletonClass *temp1=singletonClass::createInstance();///return another instance } 

благодаря

У вас может быть несколько конструкторов. C ++ предоставляет конструктор по умолчанию и конструктор копии по умолчанию, если вы не укажете его явно. Предположим, у вас есть class, который может быть создан только с помощью некоторого параметризованного конструктора. Возможно, это инициализированные переменные. Если пользователь использует этот class без этого конструктора, это может не вызвать проблем. Хорошее общее правило: если реализация по умолчанию недопустима, сделайте как конструктор по умолчанию, так и экземпляр копии закрытым и не обеспечите реализацию:

 class C { public: C(int x); private: C(); C(const C &); }; 

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

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

  1. Шаблон дизайна Singleton
  2. Чтобы ограничить количество создания экземпляра
  3. Чтобы дать осмысленное имя для создания объекта, используя статический заводский метод
  4. Статический class полезности или постоянный class
  5. Чтобы предотвратить подclass
  6. Builder Design Pattern и, следовательно, для создания неизменяемых classов

когда вы не хотите, чтобы пользователи создавали экземпляры этого classа или создавали class, который наследует этот class, например java.lang.math , вся функция в этом пакете static , все функции можно вызвать без создания экземпляра math , поэтому конструктор объявляется как статический.

Вывод из Эффективной Java , вы можете иметь class с частным конструктором, чтобы иметь class утилиты, который определяет константы (как статические конечные поля).

( EDIT: в соответствии с комментарием это то, что может быть применимо только к Java, я не знаю, применима ли эта конструкция для других языков OO (скажем, C ++))

Пример, как показано ниже:

 public class Constants { private Contants(): public static final int ADDRESS_UNIT = 32; ... } 

EDIT_1 : Опять же, ниже объяснение применимо в Java: (и ссылаясь на книгу « Эффективная Java» )

Создание экземпляра classа утилиты, как показано ниже, хотя и не является вредным, не имеет никакой цели, поскольку они не предназначены для создания экземпляров.

Например, скажем, что нет частного конструктора для констант classа. Блок кода, как показано ниже, действителен, но не лучше передает намерение пользователя classа Constants

 unit = (this.length)/new Constants().ADDRESS_UNIT; 

в отличие от кода, подобного

 unit = (this.length)/Constants.ADDRESS_UNIT; 

Кроме того, я считаю, что частный конструктор лучше передает намерение дизайнера classа Constants (say).

Java предоставляет стандартный конструктор без параметров, если конструктор не предоставлен, и если вы намерены предотвратить создание экземпляра, необходим частный конструктор.

Нельзя отметить статический class высшего уровня, и даже окончательный class может быть создан.

Утилиты могут иметь частные конструкторы. Пользователи classов не должны создавать экземпляры этих classов:

 public final class UtilityClass { private UtilityClass() {} public static utilityMethod1() { ... } } 

Вы можете запретить создание экземпляра classа. В качестве примера рассмотрим шаблон модели singleton. Чтобы гарантировать уникальность, вы не можете позволить кому-либо создать его экземпляр 🙂

Одним из важных применений является class SingleTon

 class Person { private Person() { //Its private, Hense cannot be Instantiated } public static Person GetInstance() { //return new instance of Person // In here I will be able to access private constructor } }; 

Его также подходит, если ваш class имеет только статические методы. т.е. никто не должен создавать экземпляр classа

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

Пример Factory вполне очевиден, позвольте мне продемонстрировать идиому Named Constructor .

Скажем, у меня есть class Complex который может представлять собой комплексное число.

 class Complex { public: Complex(double,double); .... }; 

Возникает вопрос: ожидает ли конструктор действительная и мнимая части, или он ожидает норму и угол (полярные координаты)?

Я могу изменить интерфейс, чтобы упростить его:

 class Complex { public: static Complex Regular(double, double = 0.0f); static Complex Polar(double, double = 0.0f); private: Complex(double, double); }; // class Complex 

Это называется идиомой Named Constructor : class можно создавать только с нуля, явно указывая, какой конструктор мы хотим использовать.

Это особый случай многих методов строительства. Шаблоны проектирования предоставляют большое количество способов создания объекта: Builder , Factory , Abstract Factory , … и частный конструктор гарантируют, что пользователь будет правильно ограничен.

В дополнение к более известным применениям …

Чтобы реализовать шаблон объекта метода , который я бы обобщил как:

«Частный конструктор, общеansible статический метод»
«Объект для реализации, функция для интерфейса»

Если вы хотите реализовать функцию с использованием объекта, а объект не полезен вне выполнения одноразового вычисления (вызовом метода), то у вас есть объект Throwaway . Вы можете инкапсулировать создание объекта и вызов метода статическим методом, предотвращая этот общий анти-шаблон:

 z = new A(x,y).call(); 

… заменяя его вызовом функции (имен):

 z = Af(x,y); 

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

Например, если вы хотите разбить вычисление между методами foo , bar и zork , например, для совместного использования состояния без необходимости передавать много значений внутри и вне функций, вы можете реализовать его следующим образом:

 class A { public static Z f(x, y) { A a = new A(x, y); a.foo(); a.bar(); return a.zork(); } private A(X x, Y y) { /* ... */ }; } 

Этот шаблон объекта метода задан в Smalltalk Best Practice Patterns , Kent Beck, стр. 34-37, где это последний шаг шаблона рефакторинга, заканчивающийся:

  1. Замените исходный метод на тот, который создает экземпляр нового classа, построенный с параметрами и получателем исходного метода, и вызывает «вычисление».

Это значительно отличается от других примеров здесь: class является реальным (в отличие от classа утилиты), но экземпляры являются частными (в отличие от заводских методов, включая синглтоны и т. Д.), И могут жить в стеке, поскольку они никогда не убегают.

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

Иногда полезно, если вы хотите контролировать, как и когда (и сколько) экземпляров объекта создаются.

Среди прочего, используется в шаблонах:

 Singleton pattern Builder pattern 

При использовании частных конструкторов также можно было бы повысить удобочитаемость / ремонтопригодность перед лицом управляемой доменом конструкции. От «Microsoft .NET – Архивирование приложений для предприятия, второе издание»:

 var request = new OrderRequest(1234); 

Цитата: «Здесь есть две проблемы: во-первых, когда вы смотрите на код, вряд ли можно догадаться, что происходит. Создается экземпляр OrderRequest, но почему и с помощью каких данных? Что такое 1234? Это приводит к второй проблеме: вы нарушаете вездесущий язык ограниченного контекста. Возможно, язык говорит примерно так: клиент может выдавать запрос на заказ и ему разрешено указывать идентификатор покупки. Если это так, вот лучший способ получить новый экземпляр OrderRequest :»

 var request = OrderRequest.CreateForCustomer(1234); 

где

 private OrderRequest() { ... } public OrderRequest CreateForCustomer (int customerId) { var request = new OrderRequest(); ... return request; } 

Я не защищаю это для каждого отдельного classа, но для вышеупомянутого сценария DDD я считаю, что имеет смысл предотвратить прямое создание нового объекта.

  • Как определить операторы подмножества для classа S4?
  • Множественное наследование в java
  • Как подключить одну панель к другой
  • Функциональное программирование заменяет шаблоны дизайна GoF?
  • Что скрывает метод в Java? Даже объяснение JavaDoc сбивает с толку
  • Какова точка частной чистой виртуальной функции?
  • Есть ли способ получить «защищенный» элемент другого объекта из производного типа?
  • В чем разница между литьем и принуждением?
  • Какое определение «интерфейс» в объектно-ориентированном программировании
  • Когда следует использовать структуру вместо classа?
  • Как реализовать class в C?
  • Interesting Posts
    Давайте будем гением компьютера.