When do we need a private constructor in C++?
Asked Answered
F

9

72

I have a question about private constructors in C++. If the constructor is private, how can I create an instance of the class?

Should we have a getInstance() method inside the class?

Fissile answered 4/7, 2011 at 7:25 Comment(0)
C
76

There are a few scenarios for having private constructors:

  1. Restricting object creation for all but friends; in this case all constructors have to be private

    class A
    {
    private:
       A () {}
    public:
       // other accessible methods
       friend class B;
    };
    
    class B
    {
    public:
       A* Create_A () { return new A; }  // creation rights only with `B`
    };
    
  2. Restricting certain type of constructor (i.e. copy constructor, default constructor). e.g. std::fstream doesn't allow copying by such inaccessible constructor

    class A
    {
    public:
       A();
       A(int);
    private:
       A(const A&);  // C++03: Even `friend`s can't use this
       A(const A&) = delete;  // C++11: making `private` doesn't matter
    };
    
  3. To have a common delegate constructor, which is not supposed to be exposed to the outer world:

    class A
    {
    private: 
      int x_;
      A (const int x) : x_(x) {} // common delegate; but within limits of `A`
    public:
      A (const B& b) : A(b.x_) {}
      A (const C& c) : A(c.foo()) {}
    };
    
  4. For singleton patterns when the singleton class is not inheritible (if it's inheritible then use a protected constructor)

    class Singleton
    {
    public:
       static Singleton& getInstance() {
          Singleton object; // lazy initialization or use `new` & null-check
          return object;
       }
    private:
       Singleton() {}  // make `protected` for further inheritance
       Singleton(const Singleton&);  // inaccessible
       Singleton& operator=(const Singleton&);  // inaccessible
    };
    
Chimborazo answered 4/7, 2011 at 7:28 Comment(6)
Actually, it could be a protected static if the class is meant to subclass and only used from subclasses.Azerbaijan
I don't understand the "upvotes" for @larsm comment. It's not meaningful.Lindon
@Alf: it's not anymore, but before it said "which must be public static".Azerbaijan
It would be great to have examples for each of the cases in the post.Balladist
Another would be when we don't want to create copyable objects. The reason for not making copyable object could be to avoid shallow copy.Berne
10 years late but for the getInstance() method it should be static Singleton object, not Singleton objectOsmose
I
22

A private constructor is commonly used with Builder methods, for example in the Named Constructor idiom.

class Point
{
public:
  static Point Polar(double, double);
  static Point Cartesian(double, double);
private:
  Point(double,double);
};

In this (typical) example, the Named Constructor idiom is used to make it explicitly which coordinate system is used to build the Point object.

Inaccessible answered 4/7, 2011 at 7:37 Comment(2)
True. A detailed example is available hereToughie
This is the most common case I know. Another term for builder method is static factory method.Maggiore
D
14

A private constructor is useful when you want to control the object creation of a class.

Let’s try in code:

#include <iostream>
using namespace std;

class aTestClass
{
    aTestClass() ////////// Private constructor of this class
    {
        cout << "Object created\n";
    }
    public:

};

int main()
{
    aTestClass a;
    aTestClass *anObject;
}

The line aTestClass a causes an error because this line is indirectly trying to access the private constructor. Comment out this line and run the program. It runs absolutely fine. Now the question is how to create the object in a such case. Let's write another program.

#include <iostream>
using namespace std;

class aTestClass
{
    aTestClass() ////////// Private constructor of this class
    {
        cout << "Object created\n";
    }
    public:

    aTestClass* getAnObject() ///// A public method create an object of this class and return the address of an object of that class
    {
        return (new aTestClass);
    }
};

int main()
{
    //aTestClass a;
    aTestClass *anObject = NULL;
    anObject = anObject->getAnObject();
}

The output is

Object created

so we have created an object of the class containing a private constructor.

Use this concept to implement a singleton class

Deirdra answered 3/5, 2013 at 11:23 Comment(0)
C
4

Yes, this is commonly used in the Singleton pattern where the object is accessed through a static member function.

Cultivable answered 4/7, 2011 at 7:27 Comment(0)
U
2

If some constructor is private, it means that no one but the class itself (and friends) should be able to create instances of it using that constructor. Therefore, you can provide static methods like getInstance() to create instances of the class or create the instances in some friend class/method.

Unreserved answered 4/7, 2011 at 7:30 Comment(0)
S
2

It depends on why the constructor was made private in the first place (you should ask whoever wrote the class you are editing). Sometimes a constructor may be made private to disallow copy construction (while allowing construction through some other constructor). Other times a constructor may be made private to disallow creating the class except by the class's "friend"s (this is commonly done if the class is a "helper" that should only be used by the class(es) for which the helper class was created). A constructor may also be made private to force the use of a (usually static) creation function.

Scent answered 4/7, 2011 at 7:31 Comment(0)
L
1

If you create a private constructor you need to create the object inside the class

#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;
}
Loosejointed answered 20/5, 2021 at 5:18 Comment(0)
A
0

A private constructor in C++ can be used for restricting object creation of a constant structure. And you can define a similar constant in the same scope like enum:

struct MathConst{
    static const uint8 ANG_180 = 180;
    static const uint8 ANG_90  = 90;

    private:
        MathConst(); // Restricting object creation
};

Access it like MathConst::ANG_180.

Amongst answered 29/11, 2018 at 8:55 Comment(1)
The purpose of this is defeated by namespaces, you can just replace struct with namespace and everything will work while beaing much cleaner.Antonetteantoni
S
0

I use it in combination with friend function(s) returning std::optional in order to safely construct objects while avoiding exceptions. For example:

#include <optional>

class Object {
private:
    Object(...) { /* ... */ }

    friend std::optional<Object> make_object(...);
};

std::optional<Object> make_object(...)
{
    // ...
    if (error)
        return std::nullopt;

    // else
    return std::make_optional<Object>(...);
}

And using it like:

bool f()
{
    auto opt_obj = make_object(...);
    if (!opt_obj)
        return false;

    // else
    auto obj = *std::move(opt_obj);  // API magic

    // ...

    return true;
}
Spirituel answered 24/11, 2023 at 21:8 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.