什么是在一个类中使构造函数是私人的使用?

为什么我们应该让构造函数在类中是私有的? 因为我们总是需要构造函数公开。

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

  1. 构造函数只能从类本身内部的静态工厂方法访问。 单身人士也可以属于这个类别。
  2. 一个实用程序类 ,只包含静态方法。

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

答:您的类实例是以static方法创build的。 然后将static方法声明为public

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

B.你的class级是单身人士 。 这意味着,程序中不会有一个以上的类实例存在。

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

C.(只适用于即将到来的C ++ 0x标准)你有几个构造函数。 其中一些是public ,另一些是private 。 为了减less代码的大小,公共构造函数调用私有构造函数,然后完成所有的工作。 您的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级是一个实用课程 。 这意味着,它只包含static成员。 在这种情况下,程序中不能创build任何对象实例。

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

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

哇,每个人都被困在单身的事情上。

其他事情:

  • 阻止人们在堆栈上创build你的课堂; 使私人的构造函数,只能通过工厂方法返回指针。
  • 防止创build类的副本(私人拷贝构造函数)

这对于包含通用代码的构造函数非常有用; 私人构造函数可以被其他构造函数调用,使用“this(…);” 符号。 通过在一个私有(或受保护的)构造函数中创build公共的初始化代码,你也明确地明确了它只在构造过程中被调用,而不是简单的方法:

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

我们也可以有私有的构造函数,仅在特定的类中创build对象(出于安全原因)。

一个办法是通过有一个朋友课。

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

这确保了你(具有私有构造函数的类)控制着构造函数的调用方式。

一个例子:类的静态工厂方法可以返回对象,因为工厂方法select分配它们(例如单身工厂)。

有些情况下你可能不想使用公共构造函数; 例如,如果你想要一个单身人士class。

如果您正在编写由第三方使用的程序集,则可能会有一些内部类只能由程序集创build,而不能由程序集的用户实例化。

如果它是私人的,那么你不能调用它==>你不能实例化类。 在某些情况下,像单身人士一样有用。

这里有一个讨论和更多的例子。

我看到你提出的一个问题,解决同样的问题。

简单地说,如果你不想让别人创build实例,那么就把构造函数保持在一个有限的范围内。 实际应用(例如)是单例模式。

不应该使构造函数私有。 期。 使其受到保护,所以如果需要,可以扩展课程。

编辑:我站在那,不pipe你扔在这个多lessdowvotes。 您正在切断代码未来发展的潜力。 如果其他用户或程序员真的决定扩展这个类,那么他们只需要将构造函数改为在源代码或字节代码中保护。 除了让自己的生活变得更难一些之外,你什么都不会做。 在你的构造函数的注释中join一个警告,并把它留在那里。

如果是实用类,更简单,更正确,更优雅的解决scheme是标记整个类“静态最终”,以防止扩展。 只是将构造函数标记为私有没有任何好处; 一个真正确定的用户可能总是使用reflection来获取构造函数。

有效用途:

  • protected构造函数的一个很好的用法是强制使用静态工厂方法,它允许限制实例化或池和重用昂贵的资源(DB连接,本地资源)。
  • 单身(通常不是很好的做法,但有时是必要的)

构造函数对于某些目的是私有的,比如当你需要实现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(); } 

同样,如果你想限制对象创build到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 ++提供了一个默认的构造函数和一个默认的拷贝构造函数。 假设你有一个只能使用一些参数化构造函数构造的类。 也许它初始化variables。 如果一个用户在没有这个构造函数的情况下使用这个类,它们就不会导致任何问题。 一个很好的通用规则:如果默认实现无效,则默认和复制构造函数都是私有的,不要提供实现:

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

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

以下是私有构造函数的一些用法:

  1. 单身devise模式
  2. 限制实例创build的次数
  3. 为使用静态工厂方法创build对象创build有意义的名称
  4. 静态工具类或常量类
  5. 防止子类化
  6. Builder的devise模式 ,从而创build不可变的类

从有效的Java引用,你可以有一个具有私有构造函数的类来定义常量的实用程序类(作为静态最终字段)。

编辑:根据评论,这是可能只适用于Java的东西,我不知道这个构造是适用/需要在其他面向对象的语言(如C + +))

举例如下:

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

EDIT_1 :再说一下,下面的解释适用于Java:(和从书中提到的Effective Java )

像下面这样的实用程序类的实例化虽然没有害处,但是没有任何用途,因为它们不是被devise成实例化的。

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

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

与代码类似

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

此外,我认为一个私人构造者更好地传达了常量 (说)类的devise者的意图。

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

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

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

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

你可能想阻止一个类被自由实例化。 以单例devise模式为例。 为了保证唯一性,你不能让任何人创build它的一个实例:-)

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

这实际上是一个显而易见的理由:你想构build一个对象,但是在构造函数中(在接口方面)这样做是不现实的。

Factory例子很明显,让我演示一下Named Constructor成语。

说我有一个Complex的类可以代表一个复杂的数字。

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

问题是:构造函数期望实部和虚部,还是期望规范和angular度(极坐标)?

我可以改变界面使其更容易:

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

这是许多施工方法的特例。 devise模式提供了许多构build对象的方法: BuilderFactoryAbstract Factory ,以及私有构造器将确保用户受到适当的约束。

除了更广为人知的用途之外…

要实现方法对象模式,我将其概括为:

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

如果你想使用一个对象来实现一个函数,并且这个对象在做一次性计算(通过方法调用)之外是没有用的,那么你就有一个Throwaway Object 。 您可以将对象创build和方法调用封装在一个静态方法中,防止这种常见的反模式:

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

用(名称空间)函数调用replace它:

 z = Af(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 Best Practice Patterns ,Kent Beck,第34-37页中给出,它是重构模式的最后一步,结束于:

  1. 将原始方法replace为创build新类的实例,并使用原始方法的参数和接收方构造,然后调用“计算”​​。

这与这里的其他例子有很大的不同:类是可实例化的(不像工具类),但是实例是私有的(不像工厂方法,包括单例等),并且可以在栈上生存,因为它们永远不会逃跑。

这种模式在自下而上的OOP中非常有用,其中对象用于简化低级实现,但不一定暴露于外部,与自顶向下的OOP形成鲜明对比,并且始于高级接口。

如果您想要控制对象的创build方式和时间(以及多less个),有时候会非常有用。

其中,用于模式:

 Singleton pattern Builder pattern 

使用私有构造函数也可以增加面向领域驱动devise的可读性/可维护性。 从“Microsoft .NET – 为企业构build应用程序,第二版”:

 var request = new OrderRequest(1234); 

引用:“这里有两个问题:首先,在查看代码的时候,很难猜测发生了什么,OrderRequest的实例正在创build,但是为什么要使用哪些数据?什么是1234?这导致了第二个问题:您违反了有界的语境中无处不在的语言,语言可能会这样说:客户可以发出一个订单请求,并且可以指定一个购买ID,如果是这样的话,这里有一个更好的方法来获得一个新的OrderRequest实例”

 var request = OrderRequest.CreateForCustomer(1234); 

哪里

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

我不是为每一个class级提倡这个,但是对于上面的DDD情况,我认为防止直接创build一个新的对象是完全合理的。