À quoi bon rendre un constructeur privé dans une classe?

pourquoi rendre le constructeur privé en classe? Comme nous avons toujours besoin que le constructeur soit public.

120
oop
demandé sur Max Galkin 2010-01-14 09:29:09

23 réponses

Certaines raisons, vous pouvez avoir besoin constructeur privé:

  1. le constructeur n'est accessible qu'à partir de static factory method à l'intérieur de la classe elle-même. Singleton peut aussi appartenir à cette catégorie.
  2. classe d'utilité , qui ne contient que des méthodes statiques.
115
répondu nanda 2010-01-14 06:33:28

en fournissant un constructeur privé vous empêchez les instances de classe d'être créées dans un autre endroit que cette classe même. Il existe plusieurs cas d'utilisation pour fournir un tel constructeur.

A. vos instances de classe sont créées selon la méthode static . La méthode static est alors déclarée comme public .

class MyClass()
{
private:
  MyClass() { }

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

B. votre classe est une singleton . Cela signifie, pas plus d'une instance de votre la classe existe dans le programme.

class MyClass()
{
private:
  MyClass() { }

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

C. (Ne s'applique qu'au prochain standard C++0x) vous avez plusieurs constructeurs. Certains d'entre eux sont déclarés public , d'autres private . Pour réduire la taille du code, les constructeurs publics "appellent" les constructeurs privés qui, à leur tour, font tout le travail. Vos constructeurs public sont ainsi appelés délégant constructeurs:

class MyClass
{
public:
  MyClass() : MyClass(2010, 1, 1) { }

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

D. vous voulez limiter l'objet copie (par exemple, à cause de l'utilisation d'une ressource partagée):

class MyClass
{
  SharedResource * myResource;

private:
  MyClass(const MyClass & theOriginal) { }
};

E. votre classe est une classe utilitaire . Cela signifie qu'il ne contient que des membres static . Dans ce cas, aucune instance objet ne doit jamais être créée dans le programme.

89
répondu Kerido 2010-03-05 12:54:28

pour laisser une" porte dérobée " qui permet à une autre classe/fonction d'amis de construire un objet d'une manière interdite à l'utilisateur. Un exemple qui vient à l'esprit serait un conteneur construisant un itérateur (C++):

Iterator Container::begin() { return Iterator(this->beginPtr_); }
// Iterator(pointer_type p) constructor is private,
//     and Container is a friend of Iterator.
12
répondu Emile Cormier 2010-01-14 08:43:05

tout le monde est coincé sur la chose Singleton, wow.

autres choses:

  • empêcher les gens de créer votre classe sur la pile; faire des constructeurs privés et seulement remettre des pointeurs par une méthode d'usine.
  • empêcher la création de copys de la classe (private copy constructor)
8
répondu Terry Mahaffey 2010-01-14 07:38:16

cela peut être très utile pour un constructeur qui contient un code commun; les constructeurs privés peuvent être appelés par d'autres constructeurs, en utilisant le 'Ceci(...);' notation. En faisant le code d'initialisation commun dans un constructeur privé( ou protégé), vous précisez aussi explicitement qu'il est appelé seulement pendant la construction, ce qui n'est pas le cas s'il s'agit simplement d'une méthode:

public class Point {
   public Point() {
     this(0,0); // call common constructor
   }
   private Point(int x,int y) {
     m_x = x; m_y = y;
   }
};
7
répondu Will 2010-01-14 06:38:55

il y a des cas où vous pourriez ne pas vouloir utiliser un constructeur public; par exemple si vous voulez une classe singleton.

si vous écrivez un assemblage utilisé par des tiers, il peut y avoir un certain nombre de classes internes que vous voulez seulement créer par votre assemblage et ne pas être instancié par les utilisateurs de votre assemblage.

3
répondu Kane 2010-01-14 06:39:03

cela garantit que vous (la classe avec le constructeur privé) contrôlez comment le contructeur est appelé.

un exemple : une méthode d'usine statique sur la classe pourrait retourner des objets comme la méthode d'usine choisit de les allouer (comme une usine singleton par exemple).

3
répondu Preet Sangha 2010-03-05 09:47:04

nous pouvons aussi avoir un constructeur privé, avant la création de l'objet par une classe spécifique seulement(Pour des raisons de sécurité).

une façon de le faire est d'avoir une classe d'amis.

c++ exemple:

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

Note: Note: Seulement ClientClass (car il est ami de SecureClass) peut appeler le constructeur de SecureClass.

3
répondu vijayNidumolu 2012-10-11 19:01:34

si c'est privé, alors vous ne pouvez pas l'appeler ==> vous ne pouvez pas instancier la classe. Utile dans certains cas, comme un singleton.

il y a une discussion et quelques autres exemples ici .

1
répondu Seth 2010-01-14 06:33:54

j'ai vu une question de vous abordant la même question.

simplement si vous ne voulez pas permettre aux autres de créer des instances, alors gardez le constuctor dans une portée limitée. L'application pratique (Un exemple) est un singleton.

1
répondu Chathuranga Chandrasekara 2010-01-14 06:35:08

Vous ne devrait pas faire le constructeur privé. Période. Faire protégées, de sorte que vous pouvez étendre la classe, si vous en avez besoin.

Edit: je suis debout par qui, n'importe comment beaucoup de downvotes vous jeter sur cette. Vous coupez le potentiel de développement futur du code. Si d'autres utilisateurs ou programmeurs sont vraiment déterminés à étendre la classe, alors ils vont juste changer le constructeur à protégé dans la source ou bytecode. Vous n'aurez rien accompli d'autre que de rendre leur vie un peu plus difficile. Incluez un avertissement dans les commentaires de votre constructeur, et laissez tomber.

S'il s'agit d'une classe d'utilité, la solution la plus simple, la plus correcte et la plus élégante est de marquer toute la classe" final statique " pour éviter l'extension. Il ne sert à rien de simplement marquer le constructeur privé; un utilisateur vraiment déterminé peut toujours utiliser la réflexion pour obtenir le constructeur.

Valide utilise:

  • Une bonne utilisation d'un protected le constructeur doit forcer l'utilisation de méthodes de fabrique, qui vous permettent de instanciation limite ou pool & reuse ressources coûteuses (connexions DB), ressources autochtones).
  • Singletons (généralement pas une bonne pratique, mais il est parfois nécessaire)
1
répondu BobMcGee 2010-01-14 14:25:19

Constructor est privé pour un but comme quand vous avez besoin d'implémenter singleton ou de limiter le nombre d'objet d'une classe. Par exemple dans la mise en œuvre singleton nous devons rendre le constructeur privé

#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();
}

encore une fois si vous voulez limiter la création de l'objet jusqu'à 10 puis utiliser le suivant

#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

}

Merci

1
répondu Tunvir Rahman Tusher 2013-05-14 15:28:06

Vous pouvez avoir plus d'un constructeur. C++ fournit un constructeur par défaut et un constructeur de copie par défaut si vous ne fournissez pas explicitement. Supposons que vous ayez une classe qui ne peut être construite qu'en utilisant un constructeur paramétré. Peut-être qu'il a initialisé des variables. Si un utilisateur utilise ensuite cette classe sans constructeur, ils peuvent causer de problèmes. Une bonne règle générale: si l'implémentation par défaut n'est pas valide, rendez le constructeur par défaut et le constructeur de copie privés et ne le faites pas. fournir une mise en œuvre:

class C
{
public:
    C(int x);

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

Utiliser le compilateur pour empêcher les utilisateurs d'utiliser l'objet avec les constructeurs par défaut qui ne sont pas valides.

1
répondu Charles 2013-08-02 17:57:53

quand vous ne voulez pas que les utilisateurs créent des instances de cette classe ou créent une classe qui hérite de cette classe, comme le java.lang.math , toute la fonction dans ce paquet est static , toutes les fonctions peuvent être appelées sans créer une instance de math , donc le constructeur est annoncé comme statique.

1
répondu shinxg 2018-05-14 13:01:43

citant Java efficace , vous pouvez avoir une classe avec le constructeur privé pour avoir une classe d'utilité qui définit les constantes (comme champs finaux statiques).

( EDIT: selon le commentaire, c'est quelque chose qui pourrait être applicable qu'avec Java, je suis pas si cette construction est applicable/nécessaires dans d'autres langages à objets (par exemple, C++))

exemple ci-dessous:

"151900920"

EDIT_1: Again, below explanation is applicable in Java : (and referring from the book, Effective Java)

An instantiation of utility class like the one below ,though not harmful, doesn't serve any purpose since they are not designed to be instantiated.

For example, say there is no private Constructor for class Constants. A code chunk like below is valid but doesn't better convey intention of the user of Constants class

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

en contraste avec le code comme

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

aussi je pense qu'un constructeur privé communique l'intention du concepteur du constantes (disons) de la meilleure classe.

Java fournit un constructeur public par défaut sans paramètre si aucun constructeur est fourni, et si votre intention est d'empêcher l'instanciation puis un constructeur privé est nécessaire.

on ne peut pas marquer une classe supérieure statique et même une classe finale peut être instanciée.

0
répondu sateesh 2010-01-14 17:46:01

Utilitaire de classes ont les constructeurs privés. Les utilisateurs des classes ne devraient pas pouvoir instancier ces classes:

public final class UtilityClass {
    private UtilityClass() {}

    public static utilityMethod1() {
        ...
    }
}
0
répondu gpampara 2010-01-16 12:40:34

vous pouvez empêcher qu'une classe soit instanciée librement. Voir le modèle de conception singleton comme un exemple. Afin de garantir l'unicité, vous ne pouvez laisser personne créer une instance de celui-ci: -)

0
répondu Seb 2010-03-05 09:49:26

L'une des utilisations importantes est dans la classe 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
   }
};

est également adapté, si votre classe n'a que des méthodes statiques. I. e personne n'a besoin d'instancier votre classe

0
répondu SysAdmin 2010-03-05 09:55:04

C'est vraiment une raison évidente: vous voulez construire un objet, mais c'est pas pratique de le faire (en terme d'interface) dans le constructeur.

l'exemple Factory est assez évident, laissez-moi vous montrer l'idiome Named Constructor .

dis que j'ai une classe Complex qui peut représenter un nombre complexe.

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

la question Est: le constructeur attend-il les parties réelles et imaginaires, ou le fait-il attend la norme et l'angle (coordonnées polaires)?

je peux changer l'interface pour la rendre plus facile:

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

cela s'appelle l'idiome Named Constructor : la classe ne peut être construite à partir de zéro en indiquant explicitement quel constructeur nous voulons utiliser.

C'est un cas particulier de nombreuses méthodes de construction. Les Modèles de conception offrent un bon nombre de façons de construire l'objet: Builder , Factory , Abstract Factory , ... et un constructeur privé veillera à ce que l'utilisateur soit correctement contraint.

0
répondu Matthieu M. 2010-03-05 12:19:32

en plus des utilisations plus connues ...

pour mettre en œuvre la méthode objet modèle, que je résumerais comme:

"constructeur Privé, public la méthode statique"

"L'objet de la mise en œuvre, en fonction de l'interface"

si vous voulez implémenter une fonction en utilisant un objet, et que l'objet n'est pas utile en dehors de la réalisation d'un one-off calcul (par appel de méthode), puis vous avez un Throwaway Object . Vous pouvez encapsuler la création d'objet et l'appel de méthode dans une méthode statique, empêchant ce commun anti-modèle:

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

...le remplaçant par un appel de fonction (namespaced):

z = A.f(x,y);

l'appelant n'a jamais besoin de savoir ou de se soucier que vous utilisez un objet à l'interne, donnant une interface plus propre, et empêchant les déchets de l'objet suspendu utilisation approximative ou incorrecte de l'objet.

par exemple, si vous voulez casser un calcul à travers les méthodes foo , bar , et zork , par exemple pour partager l'état sans avoir à passer beaucoup de valeurs dans et hors des fonctions, vous pouvez l'implémenter comme suit:

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) { /* ... */ };
}

Cette Méthode de l'Objet modèle est donné dans Smalltalk Meilleures Pratiques , Kent Beck, pages 34 à 37, où c'est la dernière étape de un refactoring modèle, en terminant:

  1. remplacer la méthode originale par une méthode qui crée une instance de la nouvelle classe, construite avec les paramètres et le récepteur de la méthode originale, et invoque "calculer".

ceci diffère significativement des autres exemples ici: la classe est instanciable (contrairement à une classe utilitaire), mais les instances sont privées (contrairement aux méthodes d'usine, y compris singletons etc.), et peuvent vivre sur la pile, puisqu'ils ne s'échappent jamais.

Ce modèle est très utile dans bottoms-up OOP, où les objets sont utilisés pour simplifier la mise en œuvre de bas niveau, mais ne sont pas nécessairement exposés à l'extérieur, et contraste avec L'OOP Descendant qui est souvent présenté et commence avec des interfaces de haut niveau.

0
répondu Nils von Barth 2015-03-04 05:26:06

est Parfois utile si vous voulez contrôler quand et comment (et combien) les instances d'un objet sont créés.

entre autres, utilisé dans les modèles:

Singleton pattern
Builder pattern
0
répondu ssedano 2015-03-04 22:05:04

sur l'utilisation de constructeurs privés pourrait également être d'accroître la lisibilité/maintenabilité face à la conception par domaine. Partir De "De Microsoft .NET - Architecing d'Applications pour l'Entreprise, 2e Édition":

var request = new OrderRequest(1234);

citation, " il y a deux problèmes ici. Tout d'abord, en regardant le code, on peut à peine deviner ce qui se passe sur. Une instance de OrderRequest est créée, mais pourquoi et en utilisant quelles données? C'est quoi, 1234? Ce conduit au deuxième problème: vous êtes violant le langage omniprésent du contexte limité. Le la langue dit probablement quelque chose comme ceci: un client peut émettre une demande d'ordre et est autorisé à spécifiez un ID d'achat. Si c'est le cas, voici une meilleure façon d'obtenir une nouvelle OrderRequest exemple:"

var request = OrderRequest.CreateForCustomer(1234);

private OrderRequest() { ... }

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

Je ne préconise pas cela pour chaque classe, mais pour le scénario DDD ci-dessus je pense qu'il est parfaitement sensé d'empêcher une création directe d'un nouvel objet.

0
répondu Morten Nørgaard 2016-10-26 07:23:51