When is a private constructor not a private constructor?
The trick is in C++14 8.4.2/5 [dcl.fct.def.default]:
... A function is user-provided if it is user-declared and not explicitly defaulted or
deleted on its first declaration. ...
Which means that C
's default constructor is actually not user-provided, because it was explicitly defaulted on its first declaration. As such, C
has no user-provided constructors and is therefore an aggregate per 8.5.1/1 [dcl.init.aggr]:
An aggregate is an array or a class (Clause 9) with no user-provided constructors (12.1), no private or
protected non-static data members (Clause 11), no base classes (Clause 10), and no virtual functions (10.3).
Why does a private base class constructor result in Implicit super constructor is not visible
if B extends A
, B
must have an access to an A
constructor.
Keep in mind that a constructor always call super()
.
So here, the implicit parameterless constructor of B
can't call the A
constructor.
Why do we need a private constructor at all?
We can't instantiate more than one object at a time via private constructors.
No, we can. A private
constructor only avoids instance creation outside the class. Therefore, you are responsible for deciding in which cases a new object should be created.
And as expected both the strings are being printed. Did I miss something?
You are creating a new instance every time the getInstance
method is called. But your commented code contains a standard lazy initialization implementation of the singleton pattern. Uncomment these parts to see the difference.
Other singleton implementations you can look over here.
Use of a private constructor
It is a private constructor. This means that outside classes cannot create new instances using the default constructor.
A little more info
All Objects
in Java
have a default constructor:
public MyObject() {}
That is how you can have this class:
public class MyObject{}
and still be able to call:
MyObject mObj = new MyObject();
Private Constructors
Sometimes a developer may not want this default constructor to be visible. Adding any other constructor will nullify this constructor. This can either be a declared constructor with empty parameters (with any of the visibility modifiers) or it can be a different constructor all together.
In the case above, it is likely that one of the following models is followed:
The Settings object is instantiated within the Settings class, and is where all the code is run (a common model for
Java
- where such a class would also contain astatic main(String[] args)
method).The Settings object has other, public constructors.
The Settings object is a
Singleton
, whereby onestatic
instance of the Settings Object is provided to Objects through an accessor method. For example:
public class MyObject {
private static MyObject instance;
private MyObject(){}//overrides the default constructor
public static MyObject sharedMyObject() {
if (instance == null)
instance = new MyObject();//calls the private constructor
return instance;
}
}
Issues related to declaration of private constructor in a class
Simple words, object or instance can't be created for that class.
As soon as, you write this statement below. For example
SomeClass c = new SomeClass(); // this will give an exception.
Basically, private constructors are used for making singleton classes.
why private constructor prevents object creation C++
To create an object in C++, a constructor needs to be called. If the constructor that needs to be invoked is not accessible, then it can't be called, and the object cannot be created.
The point of a private
constructor is not preventing object construction. It is about controlling which code can access the constructor, and therefore limiting which code to create an object that is an instance of that class. A private
constructor is accessible to all member functions (static
or otherwise) of the class, and to all declared friend
s of the class (which may be individual functions, or other classes) - so any of those can create an instance of the class using a private
constructor (assuming the constructor is defined).
If the constructor cannot be invoked, the object cannot be initialised. After all, the job of the constructor is to initialise the object. But if the constructor is inaccessible, then the object cannot be constructed, so it is not possible to have an uninitialised object.
Of course, there is nothing preventing the class from having multiple constructors with different access controls (private
, protected
, and public
). A class
with a public
constructor can be constructed, using that constructor, by any code. But any attempt to use a private
constructor (by a non-member non-friend
) will still be rejected. So access control allows the (developer of the) class
some measure of control over how an instance is constructed.
Not defining (i.e. not implementing) a constructor does prevent construction of an object. If that constructor is private
, the compiler will reject an attempt to call it (unless the function attempting to create an instance is a member or a friend
, as above). For members and friends of the class, the compiler will permit access to the constructor, but (in a typical compile-then-link toolchain) the linker will not build an executable, since it cannot resolve a call to a function that is not defined. Using the technique of marking a constructor private
and not defining it is a common way of preventing code from constructing an instance of the class (by either preventing the code from compiling, or preventing it from running).
Do constructors always have to be public?
No, Constructors can be public
, private
, protected
or default
(no access modifier at all).
Making something private
doesn't mean nobody can access it. It just means that nobody outside the class can access it. So private
constructor is useful too.
One of the use of private
constructor is to serve singleton classes. A singleton class is one which limits the number of objects creation to one. Using private
constructor we can ensure that no more than one object can be created at a time.
Example -
public class Database {
private static Database singleObject;
private int record;
private String name;
private Database(String n) {
name = n;
record = 0;
}
public static synchronized Database getInstance(String n) {
if (singleObject == null) {
singleObject = new Database(n);
}
return singleObject;
}
public void doSomething() {
System.out.println("Hello StackOverflow.");
}
public String getName() {
return name;
}
}
More information about access modifiers.
Why is private constructor still visible in case class?
Make the method A.apply(Seq[Int])
private too
A.scala
package X
object A {
def apply(x: Int): A = A(Seq(x))
private def apply(s: Seq[Int]): A = new A(s) // make explicit and private instead of auto-generated and public
}
case class A private(private val s: Seq[Int])
B.scala
package Y
import X.A
class B {
//val b = A(Seq.empty) // doesn't compile
}
Here the line val b = A(Seq.empty)
produces error
Error: polymorphic expression cannot be instantiated to expected type;
found : [A]Seq[A]
required: Int
i.e. the method A.apply(Seq[Int])
is not visible from B
.
When do we need a private constructor in C++?
There are a few scenarios for having private
constructors:
Restricting object creation for all but
friend
s; in this case all constructors have to beprivate
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`
};Restricting certain type of constructor (i.e. copy constructor, default constructor). e.g.
std::fstream
doesn't allow copying by such inaccessible constructorclass 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
};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()) {}
};For singleton patterns when the singleton
class
is not inheritible (if it's inheritible then use aprotected
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
};
How to make sure instance of a class with a private constructor can not be created from outside of the class using Reflection?
There are several ways to prevent the creation - but it is hard to tell which one is appropriate for your use-case:
Throw an exception in the constructor
You can either unconditionally throw an exception - making it (near) impossible to instantiate an instance - or only throw under certain conditions.
Some conditions can be:
- Inspecting the caller - using
StackWalker
for example. - Passing a "secret" passphrase to the constructor. JMH does this for example.
- Inspecting the caller - using
Use Java Modules.
As other modules can't deeply reflect into other named modules,
Constructor.setAccessible
will not work on your class outside of your own module.
Of course this restriction doesn't apply to your own module - but you should be able to control your own module ;).Install a
SecurityManager
.Prevents
Constructor.setAccessible
from returning successfully.
But the security manager is deprecated for removal, so I can't recommend it's use.
Note: Most of those solutions can be circumvented in some way. And it is sometimes possible to add additional defenses against that. But at the end, it'll become a game of cat and mouse.
Related Topics
How to Check If a C++ String Is an Int
Using Strtok With a Std::String
Will New Return Null in Any Case
C++11 Aggregate Initialization For Classes With Non-Static Member Initializers
Copy Constructor and = Operator Overload in C++: Is a Common Function Possible
Best Compiler Warning Level For C/C++ Compilers
Why Isn't There a Std::Shared_Ptr≪T[]≫ Specialisation
Sfinae to Check For Inherited Member Functions
Can the Template Parameters of a Constructor Be Explicitly Specified
Conversion Constructor Vs. Conversion Operator: Precedence
What Can Happen If Printf Is Called With a Wrong Format String
How to Catch Segmentation Fault in Linux
Iteration Over Std::Vector: Unsigned VS Signed Index Variable
Magic Number in Boost::Hash_Combine