Почему мы должны сделать конструктор закрытым в классе? Поскольку нам всегда нужен открытый конструктор.
Какая польза от создания конструктора в классе?
Ответ 1
Некоторые причины, по которым вам может понадобиться частный конструктор:
- Доступ к конструктору возможен только из статического factory метода внутри самого класса. Singleton также может принадлежать этой категории.
- Класс утилиты, содержащий только статические методы.
Ответ 2
Предоставляя частный конструктор, вы запрещаете создавать экземпляры экземпляров в любом месте, кроме этого самого класса. Существует несколько вариантов использования такого конструктора.
а. Экземпляры классов создаются с помощью метода static
. Затем метод static
объявляется как public
.
class MyClass()
{
private:
MyClass() { }
public:
static MyClass * CreateInstance() { return new MyClass(); }
};
В. Ваш класс - синглтон. Это означает, что в программе существует не более одного экземпляра вашего класса.
class MyClass()
{
private:
MyClass() { }
public:
MyClass & Instance()
{
static MyClass * aGlobalInst = new MyClass();
return *aGlobalInst;
}
};
С. (Применим только к предстоящему стандарту С++ 0x) У вас есть несколько конструкторов. Некоторые из них объявлены public
, другие private
. Для уменьшения размера кода публичные конструкторы "вызывают" частные конструкторы, которые, в свою очередь, выполняют всю работу. Таким образом, ваши конструкторы public
называются делегирующими конструкторами:
class MyClass
{
public:
MyClass() : MyClass(2010, 1, 1) { }
private:
MyClass(int theYear, int theMonth, int theDay) { /* do real work */ }
};
Д. Вы хотите ограничить копирование объектов (например, из-за использования общего ресурса):
class MyClass
{
SharedResource * myResource;
private:
MyClass(const MyClass & theOriginal) { }
};
Е. Класс - это класс утилиты. Это означает, что он содержит только членов static
. В этом случае экземпляр объекта никогда не должен создаваться в программе.
Ответ 3
Чтобы оставить "заднюю дверь", которая позволяет другому классу/функции друга строить объект таким образом, который запрещен пользователю. Примером, который приходит на ум, является контейнер, создающий итератор (С++):
Iterator Container::begin() { return Iterator(this->beginPtr_); }
// Iterator(pointer_type p) constructor is private,
// and Container is a friend of Iterator.
Ответ 4
Каждый застрял на вещи Синглтона, ничего себе.
Другие вещи:
- Остановить людей от создания класса в стеке; создавать частные конструкторы и только указатели обратной ссылки с помощью метода factory.
- Предотвращение создания копий класса (частный конструктор копирования)
Ответ 5
Это может быть очень полезно для конструктора, который содержит общий код; частные конструкторы могут быть вызваны другими конструкторами, используя "this (...);" нотации. Создавая общий код инициализации в частном (или защищенном) конструкторе, вы также четко указываете, что он вызывается только во время построения, что не так, если это просто метод:
public class Point {
public Point() {
this(0,0); // call common constructor
}
private Point(int x,int y) {
m_x = x; m_y = y;
}
};
Ответ 6
Это гарантирует, что вы (класс с частным конструктором) управляете вызовом конструктора.
Пример: статический метод factory в классе может возвращать объекты, поскольку метод factory делает выбор для их выделения (например, singleton factory).
Ответ 7
Мы можем также иметь частный конструктор, для создания объекта определенным классом только (Из соображений безопасности).
Один из способов сделать это - создать класс друзей.
Пример С++:
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.
Ответ 8
Есть несколько случаев, когда вы можете не использовать публичный конструктор; например, если вы хотите использовать одноэлементный класс.
Если вы пишете сборку, используемую третьими сторонами, может быть несколько внутренних классов, которые вы хотите создать только своей сборкой, а не быть созданными пользователями вашей сборки.
Ответ 9
Если он закрытый, то вы не можете его назвать == > вы не можете создать экземпляр класса. Полезен в некоторых случаях, как одиночный.
Здесь обсуждается и еще несколько примеров здесь.
Ответ 10
Я видел, как вы решали ту же проблему.
Просто, если вы не хотите разрешать другим создавать экземпляры, сохраняйте constuctor в ограниченной области. Практическое приложение (пример) - это одноэлементный шаблон.
Ответ 11
Вы не должны делать конструктор закрытым. Период. Сделайте его защищенным, поэтому вы можете расширить класс, если вам нужно.
Редактировать: Я стою рядом с этим, независимо от того, сколько нищих вы бросаете на это. Вы сокращаете потенциал для будущего развития кода. Если другие пользователи или программисты действительно намерены расширить класс, то они просто изменят конструктор на защищенный в исходном или байт-коде. Вы ничего не добьетесь, чтобы сделать их жизнь немного сложнее. Включите предупреждение в комментарии к конструктору и оставьте его на этом.
Если это класс утилиты, более простое, правильное и более элегантное решение - пометить весь класс "static final", чтобы предотвратить расширение. Не имеет никакого значения просто отметить конструктор закрытым; действительно определенный пользователь может всегда использовать отражение для получения конструктора.
Допустимое использование:
- Хорошее использование
protected
конструктор должен принудительно использовать статические factory, которые позволяют ограничить создание или пул и повторное использование дорогостоящие ресурсы (соединения БД, родные ресурсы). - Синглтоны (обычно это не хорошая практика, но иногда необходимо)
Ответ 12
Конструктор является закрытым для определенной цели, например, когда вам нужно реализовать singleton или ограничить количество объектов класса. Например, в реализации singleton мы должны сделать конструктор закрытым
#include<iostream>
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<iostream>
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
}
Спасибо
Ответ 13
У вас может быть несколько конструкторов. С++ предоставляет конструктор по умолчанию и конструктор копии по умолчанию, если вы не укажете его явно. Предположим, у вас есть класс, который может быть создан только с помощью некоторого параметризованного конструктора. Возможно, это инициализированные переменные. Если пользователь использует этот класс без этого конструктора, это может не вызвать проблем. Хорошее общее правило: если реализация по умолчанию недопустима, сделайте как конструктор по умолчанию, так и экземпляр копии закрытым и не обеспечите реализацию:
class C
{
public:
C(int x);
private:
C();
C(const C &);
};
Используйте компилятор, чтобы пользователи не могли использовать объект со стандартными конструкторами, которые недопустимы.
Ответ 14
Вот некоторые из использования частного конструктора:
- Шаблон дизайна Singleton
- Чтобы ограничить количество создания экземпляра
- Чтобы дать осмысленное имя для создания объекта с использованием статического метода factory
- Статический класс полезности или постоянный класс
- Чтобы предотвратить подкласс,
- шаблон проектирования Builder и, следовательно, для создание неизменяемых классов
Ответ 15
Утилиты могут иметь частные конструкторы. Пользователи классов не должны создавать экземпляры этих классов:
public final class UtilityClass {
private UtilityClass() {}
public static utilityMethod1() {
...
}
}
Ответ 16
Цитата из Эффективная Java, вы можете иметь класс с частным конструктором, чтобы иметь класс утилиты, который определяет константы (как статические конечные поля),
( EDIT:. В соответствии с комментарием это может быть применимо только к Java, я не знаю, применима ли эта конструкция к другим языкам OO (например, С++))
Пример, как показано ниже:
public class Constants {
private Contants():
public static final int ADDRESS_UNIT = 32;
...
}
код >
EDIT_1: Опять же, ниже объяснение применимо в Java: (и ссылаясь на книгу, Эффективная Java)
Создание класса полезности, как показано ниже, хотя и не является вредным, не служит любой цели, поскольку они не предназначены для создания экземпляров.
Например, скажем, что нет частного конструктора для констант класса.
Блок кода, как показано ниже, действителен, но не лучше передает намерение
пользователь класса Constants
unit = (this.length)/new Constants().ADDRESS_UNIT;
код >
в отличие от кода, подобного
unit = (this.length)/Constants.ADDRESS_UNIT;
код >
Также я думаю, что частный конструктор передает намерение конструктора Constants (скажем) лучше.
Java предоставляет стандартный конструктор без параметров, если конструктор , и если ваше намерение состоит в том, чтобы предотвратить создание экземпляра, то частный конструктор необходимо.
Нельзя отметить статический класс верхнего уровня, и даже окончательный класс может быть создан.
Ответ 17
Одним из важных применений является класс 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
}
};
Его также подходит, если ваш класс имеет только статические методы. i.e никто не должен создавать экземпляр класса
Ответ 18
Вы можете запретить создание экземпляра класса. В качестве примера рассмотрим шаблон модели singleton. Чтобы гарантировать уникальность, вы не можете позволить кому-либо создать экземпляр этого объекта: -)
Ответ 19
Это действительно одна очевидная причина: вы хотите создать объект, но это непрактично для этого (в терминах интерфейса) внутри конструктора.
Пример Factory
вполне очевиден, позвольте мне продемонстрировать идиому Named Constructor
.
Скажем, у меня есть класс 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
Это называется idiom Named Constructor
: класс может быть создан только с нуля, явно указывая, какой конструктор мы хотим использовать.
Это частный случай многих методов построения. Шаблоны проектирования предоставляют большое количество способов построения объекта: Builder
, Factory
, Abstract Factory
,... и частный конструктор гарантирует, что пользователь будет правильно ограничен.
Ответ 20
Иногда полезно, если вы хотите контролировать, как и когда (и сколько) экземпляров объекта создаются.
Среди других, используемых в шаблонах:
Singleton pattern
Builder pattern
Ответ 21
В дополнение к более известному использованию...
Чтобы реализовать шаблон объекта метода, в котором Id суммируется как:
"Частный конструктор, общедоступный статический метод"
"Объект для реализации, функция для интерфейса"
Если вы хотите реализовать функцию с помощью объекта, и объект не полезен вне выполнения одноразового вычисления (вызовом метода), то вы имеете Throwaway Object. Вы можете инкапсулировать создание объекта и вызов метода статическим методом, предотвращая этот общий анти-шаблон:
z = new A(x,y).call();
... заменив его вызовом функции (имен):
z = A.f(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, где это последний шаг шаблона рефакторинга, заканчивающийся:
- Замените исходный метод на тот, который создает экземпляр нового класса, построенный с параметрами и получателем исходного метода, и вызывает "вычисление".
Это значительно отличается от других примеров здесь: класс является реальным (в отличие от класса утилиты), но экземпляры являются частными (в отличие от методов factory, включая синглтоны и т.д.), и могут жить в стеке, поскольку они никогда не убегайте.
Этот шаблон очень полезен в ООП в нижней части, где объекты используются для упрощения реализации на низком уровне, но не обязательно подвергаются внешнему воздействию и контрастируют с ООП сверху вниз, который часто представлен и начинается с высокоуровневого интерфейсы.
Ответ 22
При использовании частных конструкторов также можно было бы повысить удобочитаемость/ремонтопригодность перед лицом ориентированного на домен проекта. "Microsoft.NET - Архивирование приложений для предприятия, 2-е издание":
var request = new OrderRequest(1234);
Цитата: "Здесь есть две проблемы. Во-первых, когда смотришь на код, едва ли можно догадаться, что происходит на. Создается экземпляр OrderRequest, но почему и используя какие данные? Что такое 1234? Эта приводит к второй проблеме: вы нарушаете вездесущий язык ограниченного контекста. язык, вероятно, говорит что-то вроде этого: клиент может выдать запрос на заказ и ему разрешено укажите идентификатор покупки. Если это так, heres лучший способ получить новый экземпляр OrderRequest: "
var request = OrderRequest.CreateForCustomer(1234);
где
private OrderRequest() { ... }
public OrderRequest CreateForCustomer (int customerId)
{
var request = new OrderRequest();
...
return request;
}
Я не защищаю это для каждого отдельного класса, но для вышеупомянутого сценария DDD я считаю, что имеет смысл предотвратить прямое создание нового объекта.