在类中使构造函数私有有什么用?

为什么我们要在类中将构造函数设置为私有? 因为我们总是需要将构造函数设置为公有的。

85381 次浏览

在某些情况下,您可能不希望使用公共构造函数; 例如,如果您想要一个单例类。

如果您正在编写第三方使用的程序集,则可能存在许多内部类,这些类只希望由程序集创建,而不希望由程序集的用户实例化。

您可能需要私有构造函数的一些原因:

  1. 构造函数只能从类本身内部的 静态工厂法静态工厂法访问。
  2. 一个实用程序类 ,它只包含静态方法。

如果它是私有的,那么就不能调用它 = = > ,也不能实例化类。在某些情况下很有用,比如单例模式。

有一个讨论和一些更多的例子 给你

我看到你问了同样的问题。

简单地说,如果您不想让其他人创建实例,那么将构造函数保持在有限的范围内。实际应用(例如)是单例模式。

不应该使构造函数成为私有的。就这样。使其受到保护,以便在需要时可以扩展该类。

编辑: 不管你投多少反对票,我都会支持你的观点。 您正在切断代码未来开发的潜力。如果其他用户或程序员真的决定扩展该类,那么他们只需将构造函数更改为受源代码或字节码保护。你只会让他们的日子更难过。在构造函数的注释中包含一个警告,并保留它。

如果它是一个实用程序类,那么更简单、更正确、更优雅的解决方案是将整个类标记为“ static final”,以防止扩展。仅仅将构造函数标记为 private 没有任何好处; 真正确定的用户可能总是使用反射来获取构造函数。

有效用途:

  • protected的一个好用处 构造函数是强制使用静态 工厂方法,使你可以 限制实例化或池和重用 昂贵的资源(数据库连接, 本地资源)。
  • 单例(通常不是很好的实践,但有时是必要的)

这对于包含公共代码的构造函数非常有用; 私有构造函数可以由其他构造函数使用‘ This (...) ;’表示法调用。通过在私有(或受保护)构造函数中编写通用的初始化代码,您还可以明确地表明,它只在构造期间调用,而如果它只是一个方法,则不是这样:

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

实用程序类可以有私有构造函数。这些类的用户不应该能够实例化这些类:

public final class UtilityClass {
private UtilityClass() {}


public static utilityMethod1() {
...
}
}

引用 有效的爪哇,您可以拥有一个带有私有构造函数的类,以便拥有一个定义常量(作为静态 final 字段)的实用工具类。

(编辑:根据注释,这可能只适用于 Java,我不知道这个结构是否适用于/需要其他面向对象语言(比如 C + +))

下面是一个例子:

public class Constants {
private Contants():


public static final int ADDRESS_UNIT = 32;
...
}

编辑: 同样,下面的解释适用于 Java: (参考书 有效的爪哇)

像下面这样的实用类的实例化虽然无害,但是不起作用 任何目的,因为它们不是被设计为实例化的。

例如,假设类 Constants 没有私有构造函数。 下面这样的代码块是有效的,但不能更好地表达 Constants 类的用户

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

与类似的代码形成对比

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

另外,我认为私有构造函数传达了 < i > Constants 设计者的意图 (比如)阶级更好。

如果没有构造函数,Java 提供默认的无参数公共构造函数 如果您的意图是防止实例化,那么私有构造函数就是 需要。

不能标记顶级类静态,甚至可以实例化最终类。

大家都被辛格尔顿的事困住了。

其他:

  • 阻止人们在堆栈上创建类; 创建私有构造函数,并且只能通过工厂方法返回指针。
  • 防止创建类的副本(私有复制建构子)

留下一个“后门”,允许另一个好友类/函数以用户禁止的方式构造一个对象。脑海中浮现的一个例子是构造迭代器(C + +)的容器:

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

这可以确保您(具有私有构造函数的类)控制如何调用构造函数。

例如: 类上的静态工厂方法可以在工厂方法选择分配对象时返回对象(例如单例工厂)。

通过提供一个私有构造函数,可以防止类实例在该类以外的任何地方创建。提供这样的构造函数有几种用例。

类实例是在 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;
}
};

(只适用于即将推出的 C + + 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成员。在这种情况下,不能在程序中创建任何对象实例。

其中一个重要用途是在 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
}
};

如果您的类只有静态方法,也就是说没有人需要实例化您的类,那么它也是合适的

您可能希望防止类被自由实例化。参见单例设计模式作为示例。为了保证惟一性,不能让任何人创建它的实例: -)

这真的是一个显而易见的原因: 您想要构建一个对象,但是在构造函数中这样做(就接口而言)是不切实际的。

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习惯用法: 只有通过明确说明我们希望使用哪个构造函数,才能从头构建类。

这是许多施工方法中的一个特例。设计模式提供了很多构建对象的方法: BuilderFactoryAbstract Factory,... 和一个私有构造函数将确保用户受到适当的约束。

如果您希望控制如何以及何时(以及多少)创建对象的实例,那么有时候是有用的。

其中,用于模式:

Singleton pattern
Builder pattern

我们也可以有私有构造函数, 以便通过特定的类来创建对象 仅(出于安全原因)。

一种方法是通过一个朋友班。

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 的构造函数。

构造函数在某些情况下是私有的,比如需要实现单例或限制类的对象数。 例如,在单例实现中,我们必须使构造函数私有化

#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


}

谢谢

可以有多个构造函数。C + + 提供了一个缺省构造函数和一个默认的复制建构子,如果你没有明确提供的话。假设您有一个只能使用某个参数化构造函数构造的类。也许它初始化了变量。如果用户在没有构造函数的情况下使用这个类,那么会导致无穷无尽的问题。一个很好的通用规则: 如果默认实现无效,将默认和复制建构子都设置为私有,不要提供实现:

class C
{
public:
C(int x);


private:
C();
C(const C &);
};

使用编译器可以防止用户使用具有无效的默认构造函数的对象。

除了广为人知的用途之外。

为了实现 方法对象模式,我总结如下:

“私有构造函数,公共静态方法”
“对象用于实现,函数用于接口”

如果希望使用对象实现函数,而该对象除了执行一次性计算(通过方法调用)之外没有其他用处,那么就有了 一次性物品。您可以将对象创建和方法调用封装在一个静态方法中,防止这种常见的反模式:

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

... 用一个(名称空间)函数调用替换它:

z = A.f(x,y);

调用方永远不需要知道或关心您正在内部使用对象,从而产生一个更干净的接口,并防止来自挂起的对象的垃圾或对象的不正确使用。

例如,如果您想在方法 foobarzork之间分解一个计算,例如为了共享状态而不必在函数中传入和传出许多值,您可以按以下方式实现它:

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 最佳实践模式,Kent Beck,第34-37页给出,它是重构模式的最后一步,结尾:

  1. 用一个创建新类实例的方法替换原始方法,该方法使用原始方法的参数和接收方构造,并调用“计算”。

这与这里的其他例子有很大的不同: 类是可实例化的(不同于实用程序类) ,但是实例是私有的(不同于工厂方法,包括单例等) ,并且可以存在于堆栈中,因为它们从不转义。

这种模式在自底向上的 OOP 中非常有用,在 OOP 中,对象用于简化低级实现,但不一定在外部公开,并且与自顶向下的 OOP 形成对比,后者通常以高级接口开始。

使用私有构造函数还可以提高可读性/可维护性,以应对领域驱动设计。 摘自“ Microsoft. NET-企业级应用程序架构,第2版”:

var request = new OrderRequest(1234);

引用“这里有两个问题,第一,当你看代码的时候,你几乎猜不到发生了什么 一个 OrderRequest 的实例正在被创建,但是为什么要创建并使用哪些数据? 什么是1234 导致了第二个问题: 您正在违反有界上下文的无处不在的语言 语言可能是这样说的: 客户可以发出订单请求,并被允许 指定购买 ID。如果是这种情况,这里有一个更好的方法来获得一个新的 OrderRequest 实例:

var request = OrderRequest.CreateForCustomer(1234);

哪里

private OrderRequest() { ... }


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

我并不主张对每个类都这样做,但是对于上面的 DDD 场景,我认为阻止直接创建新对象是非常有意义的。

当你不希望用户创建这个类的实例或者创建继承这个类的类时,比如 java.lang.math,这个包中的所有函数都是 static,所有的函数都可以在不创建 math实例的情况下调用,所以构造函数是静态的。

如果创建私有构造函数,则需要在类中创建对象

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;
}