Understanding Private Constructors in C++
If a constructor is made private in C++, it restricts the instantiation of the class directly from outside
its scope.
However, it can still be instantiated indirectly using certain techniques. Here's an explanation of what
happens and the use cases for making a constructor private.
1. Direct Instantiation Becomes Impossible
When the constructor is private, objects of the class cannot be created directly in the usual way
(e.g., ClassName obj; or new ClassName();).
This is because the constructor is inaccessible outside the class.
Example:
class MyClass {
private:
MyClass() { // Private constructor
cout << "Constructor called" << endl;
};
int main() {
// MyClass obj; // Error: Constructor is private
return 0;
2. How to Instantiate a Class with a Private Constructor
a. Using a Static Member Function
A static member function within the class can be used to create and return an instance of the class.
This is often used in Singleton Design Patterns.
Example:
class Singleton {
private:
static Singleton* instance;
Singleton() { // Private constructor
cout << "Constructor called" << endl;
public:
static Singleton* getInstance() {
if (!instance) {
instance = new Singleton();
return instance;
};
Singleton* Singleton::instance = nullptr;
int main() {
Singleton* obj1 = Singleton::getInstance();
Singleton* obj2 = Singleton::getInstance();
cout << (obj1 == obj2) << endl; // Outputs: 1 (Both pointers are the same)
return 0;
b. Friend Class/Function
A friend class or function can access the private constructor and create objects.
Example:
class MyClass {
private:
MyClass() { // Private constructor
cout << "Private Constructor called" << endl;
friend class FriendClass; // Declare FriendClass as a friend
};
class FriendClass {
public:
MyClass createObject() {
return MyClass(); // Accessing private constructor
};
int main() {
FriendClass f;
MyClass obj = f.createObject(); // Object created through friend class
return 0;
c. Factory Design Pattern
A factory function outside the class can create and manage instances by being declared as a friend.
Example:
class Product {
private:
Product() { // Private constructor
cout << "Product created" << endl;
public:
static Product* createProduct() {
return new Product();
};
int main() {
Product* p = Product::createProduct();
delete p;
return 0;
3. Use Cases for Private Constructors
a. Singleton Pattern
Ensures only one instance of a class is created throughout the application.
b. Restricting Object Creation
Prevents the creation of objects directly when it's not desirable.
Used when the class only contains static members and does not need instances (e.g., utility
classes).
Example:
class Utility {
private:
Utility() {} // Private constructor
public:
static int add(int a, int b) {
return a + b;
};
int main() {
// Utility obj; // Error: Constructor is private
cout << Utility::add(3, 4) << endl;
return 0;
c. Controlled Object Creation
Ensures objects are created in a controlled manner, such as through specific functions or by
adhering to certain rules.
4. Limitations of Private Constructors
Since direct instantiation is not allowed, you must provide alternative ways to create objects (e.g.,
factory methods, static methods, or friend classes).
This can complicate the code if not implemented thoughtfully.
By making the constructor private, you gain control over object creation, which is useful in scenarios
like implementing design patterns or enforcing constraints.