What is the difference in passing arguments to the base class constructor?
Dog::Dog(string input_name, int input_age) : Pet(input_name, input_age) { }
Dog::Dog(string input_name, int input_age) { Pet(input_name, input_age); }
Look the following snippet:
class Cat {
private:
const int m_legs;
public:
Cat() : m_legs{4}
{
}
};
In the snippet above this is the only way you have to initialize a constant because m_legs is initialized before the body of constructor.
Another case is exeptions managment:
class Test {
private:
ICanThrow m_throw;
public:
Cat() try : m_throw{}
{
}
catch(...)
{
// mangage exception
}
};
I usually prefer initialize member before ctor body or when I can initialize members directly in the class declaration:
class Cat {
public:
void meow()
{
}
private:
const int m_legs = 4;
string m_meow{"meow"};
};
If Pet has no default constructor, only 1) will work.
By the time you get into the actual body of the constructor all members and bases have already been constructed. So if a base class has no default constructor you need to tell the compiler which constructor you want it initialised with, and do it before the body of the constructor - this is what the initialiser list is for.
Another reason is if a base or member is const - you can't modify it in the body of the constructor.
Related
In the following, isn't _abc already assigned a value (albeit a default one) of "", then it got changed to "xyz" when I initialize MyClass ?
Why is _abc being a const as declared in MyClass's private member field not preventing it from being changed to 'xyz' ?
class MyClass{
public:
MyClass(const std::string abc);
void doIt();
private:
const std::string _abc;
};
MyClass::MyClass(const std::string abc): _abc(abc) {} //are we not changing _abc from its initialized value ? But _abc is declared as const
void MyClass::doIt(){
std::cout<<"abc is "<<_abc<<std::endl;
}
int main()
{
cout<<"Hello World"<<std::endl;
auto myObj = MyClass("xyz");
myObj.doIt();
return 0;
}
It is not 'changed' to 'xyz'. When the constructor of MyClass is called, the initialization list initializes members. Therefore, std::string's constructor is called with "xyz", which is a valid call.
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?
There are a few scenarios for having private constructors:
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`
};
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
};
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 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
};
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.
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
Yes, this is commonly used in the Singleton pattern where the object is accessed through a static member function.
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.
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.
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;
}
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.
Consider I want to wrap some library code inside an object. That library needs to be set up and initialized by calling some function inside the constructor of that wrapper class.
The librarie's "objects" then diverge into creating more, different "objects" that the wrapper class wraps in form of yet another wrapper object that should be a plain member of that class.
But as far as I see it, members of classes can only be initialized or created by calling their constructor in the initalizer list of the constructor. The execution of these bits of code preceed the constructor of the actual class that does the initialization of the library and its environment, making it impossible for me to actually initialize that member object as a member and instead force me to initialize it as a pointer to the 2nd wrapper, because its constructor must be called manually within the first constructor's code.
Example:
class A {
public:
A() {
if(!wrapped_library_init()) {
exit(CRITICAL_ERROR);
}
ptr_to_some_library_metadata *a = library_function(); /*Needs to
be called after wrapped_library_init() or needs a pointer to some
wrapped object created inside this constructor */
//initialize b
}
private:
B b; //Wants to be a member but can not
};
class B {
B(ptr_to_some_library_metadata *a);
}
Member objects can only be constructed in the member initializer list. There are a few techniques which can be used to make it possible to initialize an object, though:
Use a helper [lambda] function doing the necessary extra work before return a suitable object. For example:
A()
: B([]{
if (!wrapped_library_init()) {
exit(CRITICAL_ERROR);
}
return library_function();
}()) {
}
You can delay construction by using a union with just the appropriate member. When using this technique the member needs to be explicitly destructed, for example:
class A {
union Bu { B b };
Bu b;
public:
A() {
if (!wrapped_library_init()) {
exit(CRITICAL_ERROR);
}
new(&b.b) B(library_function());
}
~A() {
b.b.~B();
}
// ...
};
I'd personally use the first approach. However, there are cases when using a union to delay construction is helpful.
Initializer lists are there to use another constructor than the default constructor.
But nothing impedes you for creating a custom function that will initialize b:
class A {
public:
A():b(init()) {
}
private:
B b; //Wants to be a member but can not
static B init()
{
if(!wrapped_library_init()) {
exit(CRITICAL_ERROR);
}
ptr_to_some_library_metadata *a = library_function(); /*Needs to
be called after wrapped_library_init() or needs a pointer to some
wrapped object created inside this constructor */
return B(a);
}
};
Wrap your library inside a class:
class LibraryWrapper
{
public:
LibraryWrapper()
{
if(!wrapped_library_init()) {
exit(CRITICAL_ERROR);
}
lib_data.reset(library_function()); /*Needs to
be called after wrapped_library_init() or needs a pointer to some
wrapped object created inside this constructor */
}
//~LibraryWrapper() {/**/}
//LibraryWrapper(const LibraryWrapper&) {/**/} // =delete; ?
//LibraryWrapper& operator=(const LibraryWrapper&) {/**/} // =delete; ?
//private: // and appropriate interface to hide internal
std::unique_ptr<ptr_to_some_library_metadata, CustomDeleter> lib_data;
};
class B {
public:
explicit B(ptr_to_some_library_metadata *a);
// ...
};
And use extra member or inheritance:
class A
{
public:
A() : b(lib.lib_data.get()) {}
private:
LibraryWrapper lib; // placed before B
B b;
};
I am getting problems in initializing the nested class constructor.
Here is my code:
#include <iostream>
using namespace std;
class a
{
public:
class b
{
public:
b(char str[45])
{
cout<<str;
}
}title;
}document;
int main()
{
document.title("Hello World"); //Error in this line
return 0;
}
The error I get is:
fun.cpp:21:30: error: no match for call to '(a::b)'
You probably want something like:
class a
{
public:
a():title(b("")) {}
//....
};
This is because title is already a member of a, however you don't have a default constructor for it. Either write a default constructor or initialize it in the initialization list.
You have to either make your data member a pointer, or you can only call the data member's constructor from the initialiser list of the construtor of the class it is a member of (in this case, a)
This:
document.title("Hello World");
is not "initializing the nested class"; it's attempting to call operator() on the object.
The nested object is already initialised when you create document. Except that it's not, because you've provided no default constructor.
So what do you have here:
class A {
B title;
}
Without defining constructor for class A (as Luchian Grigore shown) title will be initialized as: B title();
You can work that around by:
A::A():title(B("Hello world"))
// Or by adding non parametric constructor:
class B {
B(){
}
B( const char *str){
}
}
Object title (in document) is already initialized and you cannot call constructor anymore, but you still may use syntax: document.title(...) by declaring and defining operator() but it won't be constructor anymore:
class B {
const B& operator()(const char *str){
cout << str;
return *this;
}
}
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?
There are a few scenarios for having private constructors:
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`
};
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
};
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 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
};
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.
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
Yes, this is commonly used in the Singleton pattern where the object is accessed through a static member function.
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.
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.
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;
}
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.