为什么我们要在类中将构造函数设为私有?因为我们总是需要将构造函数公开。
答案 0 :(得分:120)
您可能需要私有构造函数的一些原因:
答案 1 :(得分:91)
通过提供私有构造函数,可以防止在除此类之外的任何位置创建类实例。提供此类构造函数有几种用例。
一个。您的类实例是使用static
方法创建的。然后将static
方法声明为public
。
class MyClass()
{
private:
MyClass() { }
public:
static MyClass * CreateInstance() { return new MyClass(); }
};
B中。您的班级是单身人士。这意味着,程序中只存在一个类的实例。
class MyClass()
{
private:
MyClass() { }
public:
MyClass & Instance()
{
static MyClass * aGlobalInst = new MyClass();
return *aGlobalInst;
}
};
℃。 (仅适用于即将推出的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) { }
};
电子。您的类是实用程序类。这意味着,它只包含static
个成员。在这种情况下,不能在程序中创建任何对象实例。
答案 2 :(得分:12)
留下“后门”,允许其他朋友类/功能以禁止用户的方式构建对象。想到的一个例子是构造迭代器(C ++)的容器:
Iterator Container::begin() { return Iterator(this->beginPtr_); }
// Iterator(pointer_type p) constructor is private,
// and Container is a friend of Iterator.
答案 3 :(得分:9)
每个人都被困在单身人士身上,哇。
其他事项:
答案 4 :(得分:7)
这对包含公共代码的构造函数非常有用;私有构造函数可以被其他构造函数调用,使用'this(...);'符号。通过在私有(或受保护的)构造函数中创建公共初始化代码,您还明确表明它仅在构造期间被调用,如果它只是一个方法,则不是这样:
public class Point {
public Point() {
this(0,0); // call common constructor
}
private Point(int x,int y) {
m_x = x; m_y = y;
}
};
答案 5 :(得分:3)
在某些情况下,您可能不想使用公共构造函数;例如,如果你想要一个单例类。
如果您正在编写第三方使用的程序集,则可能有许多内部类,您只需要由程序集创建,而不是由程序集的用户实例化。
答案 6 :(得分:3)
这可以确保您(具有私有构造函数的类)控制如何调用构造函数。
示例:类上的静态工厂方法可以返回对象,因为工厂方法选择分配它们(例如,像单件工厂)。
答案 7 :(得分:3)
我们也可以拥有私有构造函数, 通过特定的类来创建对象的创建 仅(出于安全原因)。
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的构造函数。
答案 8 :(得分:2)
以下是私有构造函数的一些用法:
答案 9 :(得分:1)
我看到你提出的一个问题,解决了同样的问题。
如果您不想让其他人创建实例,那么只需将构造器保持在有限的范围内。实际应用(一个例子)是单例模式。
答案 10 :(得分:1)
你不应该使构造函数成为私有的。期。使其受到保护,因此您可以根据需要扩展该类。
编辑:无论你投入多少次投票,我都会站在那里。 你正在切断代码未来发展的潜力。如果其他用户或程序员确实要扩展该类,那么他们只需将构造函数更改为源或字节码中的受保护。除了让自己的生活更加艰难之外,你将一无所获。在构造函数的注释中包含警告,并将其保留在该注释中。
如果它是一个实用程序类,更简单,更正确,更优雅的解决方案是将整个类标记为“静态final”以防止扩展。将构造函数标记为私有没有任何好处;一个真正确定的用户可能总是使用反射来获取构造函数。
protected
的好用
构造函数是强制使用静态的
工厂方法,允许你
限制实例化或池&重用
昂贵的资源(数据库连接,
本地资源)。答案 11 :(得分:1)
如果您不希望用户创建此类的实例或创建继承此类的类(如java.lang.math
),则此包中的所有函数均为static
,则可以调用所有函数无需创建math
的实例,因此构造函数将声明为静态。
答案 12 :(得分:1)
如果它是私人的,那么你就不能称之为==>你无法实例化这个类。在某些情况下很有用,比如单身人士。
有一个讨论和更多例子here。
答案 13 :(得分:1)
您可以拥有多个构造函数。如果您没有显式提供,则C ++提供默认构造函数和默认复制构造函数。假设您有一个只能使用某些参数化构造函数构造的类。也许它初始化变量。如果用户在没有该构造函数的情况下使用此类,则它们可能导致无问题。一个很好的一般规则:如果默认实现无效,请将默认实现和复制构造函数设为私有,并且不提供实现:
class C
{
public:
C(int x);
private:
C();
C(const C &);
};
使用编译器阻止用户将该对象与默认的无效构造函数一起使用。
答案 14 :(得分:1)
构造函数是私有的,例如当您需要实现单例或限制类的对象数时。 例如,在单例实现中,我们必须使构造函数成为私有
#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
}
谢谢
答案 15 :(得分:0)
如果创建私有构造函数,则需要在类内部创建对象
enter code here#include<iostream>
//factory method
using namespace std;
class Test
{
private:
Test(){
cout<<"Object created"<<endl;
}
public:
static Test* m1(){
Test *t = new Test();
return t;
}
void m2(){
cout<<"m2-Test"<<endl;
}
};
int main(){
Test *t = Test::m1();
t->m2();
return 0;
}
答案 16 :(得分:0)
使用私有构造函数也可以提高面向域驱动设计的可读性/可维护性。 来自&#34; Microsoft .NET - 为企业构建应用程序,第2版&#34;:
var request = new OrderRequest(1234);
引用,&#34;这里有两个问题。首先,在查看代码时,很难猜出会发生什么 上。正在创建OrderRequest的实例,但为什么要使用哪些数据呢?什么是1234?这个 导致第二个问题:你违反了有界语境中普遍存在的语言。该 语言可能会这样说:客户可以发出订单请求并被允许 指定购买ID。如果是这种情况,这是获得新的OrderRequest实例的更好方法:&#34;
var request = OrderRequest.CreateForCustomer(1234);
,其中
private OrderRequest() { ... }
public OrderRequest CreateForCustomer (int customerId)
{
var request = new OrderRequest();
...
return request;
}
我并不是每个类都提倡这个,但对于上面的DDD场景,我认为防止直接创建新对象是完全合理的。
答案 17 :(得分:0)
除了更为人熟知的用途......
实现Method Object模式,我将其概括为:
“私有构造函数,公共静态方法”
“实现对象,接口函数”
如果你想使用一个对象实现一个函数,并且该对象在进行一次性计算(通过方法调用)之外没有用处,那么你有一个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页中给出,其中它是重构模式的最后一步,结束:
- 将原始方法替换为创建新类实例的方法,使用原始方法的参数和接收器构造,并调用“compute”。
醇>
这与此处的其他示例明显不同:类是可实例化的(与实用程序类不同),但实例是私有的(与工厂方法不同,包括单例等),并且可以存在于堆栈中,因为它们永远不会逃脱
这种模式在自下而上的OOP中非常有用,其中对象用于简化低级实现,但不一定是外部暴露,并且与自上而下的OOP形成对比,后者通常以高级别开始接口
答案 18 :(得分:0)
如果您想控制创建对象的实例的方式和时间(以及数量),有时会很有用。
其中,用于模式:
Singleton pattern
Builder pattern
答案 19 :(得分:0)
这是一个显而易见的原因:你想构建一个对象,但在构造函数中这样做(在接口方面)是不切实际的。
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
这称为Named Constructor
成语:只能通过明确说明我们希望使用哪个构造函数来从头构建类。
这是许多施工方法的特例。设计模式提供了许多构建对象的方法:Builder
,Factory
,Abstract Factory
,...并且私有构造函数将确保用户得到适当的约束。
答案 20 :(得分:0)
您可能希望阻止类自由地实例化。以单件设计模式为例。为了保证唯一性,你不能让任何人创建它的实例: - )
答案 21 :(得分:0)
其中一个重要用途是在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
}
};
它也适用,如果你的类只有静态方法。即没有人需要实例化你的班级
答案 22 :(得分:0)
从Effective Java引用,你可以让一个私有构造函数的类有一个定义常量的实用程序类(作为静态最终字段)。
(编辑:根据评论这可能只适用于Java,我不知道这个结构是否适用于其他OO语言(比如C ++))
如下例子:
public class Constants {
private Contants():
public static final int ADDRESS_UNIT = 32;
...
}
public class Constants {
private Contants():
public static final int ADDRESS_UNIT = 32;
...
}
EDIT_1 的: 同样,下面的解释适用于Java :(并参考书籍Effective Java)
如下所示的实用程序类的实例化虽然没有害处,但却无法实现 任何目的,因为它们不是为了实例化而设计的。
例如,假设类Constants没有私有的构造函数。
像下面这样的代码块是有效的,但不能更好地传达意图
Constants类的用户
unit = (this.length)/new Constants().ADDRESS_UNIT;
与代码相比
unit = (this.length)/new Constants().ADDRESS_UNIT;
此外,我认为私有构造函数传达了常量的设计者的意图 (比如)上课更好。
如果没有构造函数,Java提供了一个默认的无参数公共构造函数 提供,如果你的意图是防止实例化,那么私有构造函数是 需要。
无法将顶级类标记为静态,甚至可以实例化最终类。
答案 23 :(得分:0)
实用程序类可以有私有构造函数。这些类的用户不应该能够实例化这些类:
public final class UtilityClass {
private UtilityClass() {}
public static utilityMethod1() {
...
}
}