The
constructor is a member function that initializes an instance of its class. The constructor has the same name as the class and does not have a return value. A constructor can have any number of arguments, and a class can have any number of overloaded constructors. Constructors can have any accessibility (public, protected, or private). If no constructors are defined, the compiler generates a default constructor that takes no arguments, and you can override this behavior by declaring the default constructor as deleted. The
constructor order
Constructor performs work in this order:
calls the base class and member constructors in the order declared.
If a class derives from a virtual base class, the virtual base pointer of the object is initialized.
If a class has or inherits a virtual function, the object's virtual function pointer is initialized. The virtual function pointer points to a virtual function table in the class, ensuring that the virtual function invokes the binding code correctly.
It executes all the code in its own function body. The
The following example shows the order in which the base class and member constructors are called in the constructor of a derived class. First, call the base constructor, and then initialize the members in the order in which they appear in the class declaration, and then invoke the derived constructor.
#include <iostream>
using namespace std;
Class Contained1 {public
:
Contained1 () {
cout << "Contained1 constructor." << Endl;
}
};
class Contained2 {public
:
Contained2 () {
cout << "Contained2 constructor." << Endl;
}
};
Class Contained3 {public
:
Contained3 () {
cout << "Contained3 constructor." << Endl;
}
};
Class Basecontainer {public
:
Basecontainer () {
cout << "Basecontainer constructor." << Endl;
}
Private:
Contained1 C1;
CONTAINED2 C2;
};
Class Derivedcontainer:public Basecontainer {public
:
derivedcontainer (): Basecontainer () {
cout < < "Derivedcontainer constructor." << Endl
}
Private:
Contained3 c3;
int main () {
derivedcontainer dc;
int x = 3;
}
This is the output:
Contained1 constructor.
Contained2 constructor.
Basecontainer constructor.
Contained3 constructor.
Derivedcontainer constructor.
If the constructor throws an exception, the order of the destructor is the reverse of the constructed order:
The code in the constructor body is expanded.
The base class and member objects are destroyed, in reverse order from the declaration order.
If the constructor is a non delegate, all fully constructed base class objects and members are destroyed. However, the object itself is not fully constructed, so the destructor does not run.
member List
Initializes a class member from a constructor parameter using the member initializer list. This method uses direct initialization, which is more efficient than using assignment operators in the constructor body.
Class Box {public
:
box (int width, int length, int height)
: m_width (width), m_length (length), M_height ( Height)//member Init list
{}
int Volume () {return m_width * m_length * m_height;}
Private:
int m_width;
int m_length;
int m_height;
};
To create a Box object:
Box B (a);
cout << "The volume is" << b.volume ();
An explicit constructor
if the class has a constructor with one parameter, or if all parameters except one are of the default value, then the parameter type can be implicitly converted to the class type. For example, if the Box class has a constructor similar to the following:
Box (int size): m_width (size), m_length (size), m_height (size) {}
You can initialize Box, as follows:
or pass an int to the function with Box:
Class Shippingorder
{public
:
Shippingorder (Box B, double postage): M_box (b), m_postage (postage) {}
Private:
Box M_box;
Double m_postage;
}
Elsewhere ... Shippingorder SO (42, 10.8);
Such conversions may be useful in some cases, but more often, they can cause subtle but serious errors in your code. As a general rule, the constructor should use the explicit keyword (and the user-defined operator) to prevent this implicit type conversion from occurring:
explicit Box (int size): m_width (size), m_length (size), m_height (size) {}
This row causes a compiler error when the constructor is an explicit function: Shippingorder SO (42, 10.8);.
default constructor
default constructors have no parameters; they follow slightly different rules:
The default constructor is a special member function, and if no constructor is declared in the class, the compiler provides a default constructor:
Class Box {
box (int width, int length, int height)
: m_width (width), m_length (length), m_height (height) {}
};
int main () {
box box1{};//Call compiler-generated default ctor
box Box2; Call compiler-generated default ctor
}
When you invoke the default constructor and try to use parentheses, the system issues a warning:
Class myclass{};
int main () {
MyClass MC (); Warning c4930:prototyped function not called (is a variable definition intended?)
}
This is an example of the "toughest resolution" problem. This sample expression can be interpreted either as a function declaration or as a call to a default constructor, and the C + + parser is more biased towards declarations, so the expression is treated as a function declaration.
If any non-default constructors are declared, the compiler does not provide a default constructor:
Class Box {
box (int width, int length, int height)
: m_width (width), m_length (length), m_height (height) {}
};
private:
int m_width;
int m_length;
int m_height;
};
int main () {
Box box1 (1, 2, 3);
Box box2{2, 3, 4};
Box box4; Compiler error C2512:no appropriate default constructor available
}
If a class does not have a default constructor, you cannot construct an object array of that class by using the bracket syntax alone. For example, in the code block mentioned earlier, an array of boxes cannot be declared as follows:
Box boxes[3]; Compiler error C2512:no appropriate default constructor available
However, you can initialize the array of boxes using the initializer list:
Box boxes[3]{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
Copying and moving constructors
a copy constructor is a special member function that takes a reference to the same type of object as input and creates a copy of it. A move is also a special member function constructor that transfers ownership of an existing object to a new variable without copying the original data.
An explicit default constructor and a deleted constructor
you can explicitly set the default copy constructor, set default constructors, move constructors, copy assignment operators, move assignment operators, and destructors. You can explicitly delete all of the special member functions.
constructors in derived classes
a derived class constructor always calls the base class constructor, so it can rely on a fully constructed base class before any additional tasks are completed. Invokes the base class constructor for derivation, for example, if ClassA derives from Classb,classb from CLASSC, the Classc constructor is called first, then the ClassB constructor is invoked, and the ClassA constructor is called finally.
If the base class does not have a default constructor, you must supply the base class constructor parameter in the derived class constructor:
Class Box {public
:
box (int width, int length, int height) {
m_width = width;
m_length = length;
m_height = height;
}
Private:
int m_width;
int m_length;
int m_height;
};
Class Storagebox:public Box {public
:
storagebox (int width, int length, int height, const string label&): Box (width, length, height) {
m_label = label;
}
Private:
string M_label;
};
int main () {
const string Alabel = "Alabel";
Storagebox SB (1, 2, 3, Alabel);
Constructors for classes with multiple inheritance
if a class derives from more than one base class, the base class constructor is called in the order listed in the derived class declaration:
#include <iostream>
using namespace std;
Class BaseClass1 {public
:
BaseClass1 () {
cout << "BaseClass1 constructor." << Endl;
}
};
class BaseClass2 {public
:
BaseClass2 () {
cout << "BaseClass2 constructor." << Endl;
}
};
Class baseclass3{public
:
BaseClass3 () {
cout << "BaseClass3 constructor." << Endl;
}
};
Class Derivedclass:public BaseClass1, public BaseClass2, public BASECLASS3 {public
:
derivedclass () {
cout << "DerivedClass constructor." << Endl;
}
;
int main () {
derivedclass dc;
}
You should see the following output:
BaseClass1 constructor.
BaseClass2 constructor.
BaseClass3 constructor.
DerivedClass constructor.
Virtual functions in constructors
We recommend that you carefully invoke the virtual functions in the constructor. The base class constructor is always called before the derived class constructor, so the function called in the base constructor is the base class version, not the derived class version. In the following example, constructing DerivedClass causes the print_it () implementation of the BaseClass to execute earlier than the DerivedClass constructor, which causes the derivedclass () implementation to execute the PRINT_IT:
#include <iostream>
using namespace std;
Class baseclass{public
:
BaseClass () {
print_it ();
}
virtual void Print_it () {
cout << "BaseClass print_it" << Endl;
}
};
Class Derivedclass:public BaseClass {public
:
derivedclass () {
print_it ();
}
virtual void Print_it () {
cout << "Derived Class print_it" << Endl;
}
;
int main () {
derivedclass dc;
}
This is the output:
BaseClass print_it
Derived Class print_it
Constructors and composite classes
classes that contain members of a class type are called "Composite classes." When you create a class-type member of a composite class, call the constructor before calling the class's own constructor. When the containing class does not have a default constructor, you must use the initialization list in the composite class constructor. In the previous Storagebox example, if you change the type of a M_label member variable to a new label class, you must call the base class constructor and initialize the M_label variable, which is in the Storagebox constructor:
Class Label {public
:
label (const string& Name, const string& address) {m_name = name; m_address = addres S }
string M_name;
string m_address;
};
Class Storagebox:public Box {public
:
storagebox (int width, length int, int height, label label)
: Box (Widt h, length, height), M_label (label) {}
private:
label M_label;
int main () {
//passing a named label
label label1{"Some_name", "some_address"};
Storagebox SB1 (1, 2, 3, Label1);
Passing a temporary label
Storagebox SB2 (3, 4, 5, label{"Another name", "another Address"});
Passing a temporary label as an initializer list
Storagebox sb3 (1, 2, 3, {"MyName", "myaddress"});
The
delegate constructor
Delegate constructor calls the other constructors in the same class to complete part of the initialization work. In the following example, the derived class has three constructors, the second constructor delegates the first, and the third constructor delegates the second:
#include <iostream>
using namespace std;
Class Constructordestructor {public
:
constructordestructor () {
cout << "Constructordestructor Default constructor. "<< Endl;
}
Constructordestructor (int int1) {
cout << "Constructordestructor constructor with 1 int." << Endl;
}
constructordestructor (int int1, int int2): Constructordestructor (int1) {
cout << " Constructordestructor constructor with 2 ints. "<< Endl;
Throw exception ();
}
Constructordestructor (int int1, int int2, int int3): Constructordestructor (Int1, Int2) {
cout << "constructor Destructor constructor with 3 ints. "<< Endl;
}
~constructordestructor () {
cout << "Constructordestructor destructor." << Endl;
}
;
int main () {
constructordestructor DC (1, 2, 3);
}
This is the output:
Constructordestructor constructor with 1 Int.
Constructordestructor constructor with 2 ints.
Constructordestructor constructor with 3 ints.
When all constructors are complete, the fully initialized constructor creates the object immediately. Derivedcontainer (int int1) succeeded, but Derivedcontainer (int int1, int int2) failed, and the destructor was invoked.
Class Constructordestructor {public
:
constructordestructor () {
cout << "Constructordestructor Default constructor. "<< Endl;
}
Constructordestructor (int int1) {
cout << "Constructordestructor constructor with 1 int." << Endl;
}
constructordestructor (int int1, int int2): Constructordestructor (int1) {
cout << " Constructordestructor constructor with 2 ints. "<< Endl;
Throw exception ();
}
Constructordestructor (int int1, int int2, int int3): Constructordestructor (Int1, Int2) {
cout << "constructor Destructor constructor with 3 ints. "<< Endl;
}
~constructordestructor () {
cout << "Constructordestructor destructor." << Endl;
}
;
int main () {
try {
constructordestructor cd{1, 2, 3};
}
catch (const exception& ex) {
}
}
Output:
Constructordestructor constructor with 1 Int.
Constructordestructor constructor with 2 ints.
Constructordestructor destructor.
Inheritance Constructor (C++11)
a derived class can inherit a constructor from a direct base class using a using declaration, as shown in the following example:
#include <iostream> using namespace std;
Class Base {public:base () {cout << "base ()" << Endl;}
Base (const base& Other) {cout << base (base&) << Endl;}
Explicit base (int i): num (i) {cout << base (int) << Endl;}
Explicit Base (char c): letter (c) {cout << "Base (char)" << Endl;}
Private:int num;
Char letter;
};
Class Derived:base {public://Inherit all constructors from Base using Base::base;
Private://Can ' t initialize Newmember from Base constructors.
int newmember{0};
};
int main (int argc, char argv[]) {cout << "Derived D1 (5) Calls:";
Derived D1 (5);
cout << "Derived D1 (' C ') calls:";
Derived D2 (' C ');
cout << "Derived d3 = D2 calls:";
Derived d3 = D2;
cout << "Derived D4 calls:";
Derived D4;
Keep Console Open in debug mode:cout << endl << ' press Enter to exit. '
Char in[1];
Cin.getline (in, 1);
return 0; }
Derived D1 (5) calls:base (int)
Derived d1 (' C ') calls:base (char)
Derived d3 = D2 calls:base (base&)
Deriv Ed D4 calls:base ()
press Enter to exit.
The using statement can introduce all constructors from the base class to the scope except that the signature is the same as the constructor in the derived class. In general, it is best to use an inheritance constructor when a derived class does not declare a new data member or constructor.
If the type specifies a base class, the class template can inherit all constructors from the type parameter:
template< TypeName T >
class Derived:t {
using T::t; Declare the constructors from T
//...
};
If the constructor of the base class has the same signature, the derived class cannot inherit from more than one base class.
rules for declaring constructors
The constructor is the same as the name of its class. You can declare any number of constructors, depending on the rules of the overloaded function.
The argument-declaration-list may be empty.
C + + defines two special constructors (the default constructor and the copy constructor), as described in the following table.
Default constructors and copy constructors
The
default constructor can be invoked without parameters. However, if all parameters have default values, you can declare the default constructor with a parameter list. Similarly, a copy constructor must accept a single argument to a reference to the same class type. You can provide multiple parameters, provided that all subsequent parameters have a default value.
If no constructors are provided, the compiler will attempt to generate a default constructor. If a copy constructor is not provided, the compiler will attempt to generate one. These compiler-generated constructors are treated as public member functions. If you specify a copy constructor by using the first parameter that belongs to the object but not the reference, an error is generated. The
compiler-generated default constructor sets the object (as described earlier, initializes vftables and Vbtables) and calls the default constructor for the base class and members, but it does nothing else. They are called only if the base class and member constructors exist, are accessible, and are ambiguous. The
compiler-generated copy constructor sets the new object and copies the contents of the object to be copied by member. If the base class or member constructors are present, they are called, otherwise a bitwise copy is performed.
If all the base classes and member classes of class type have a copy constructor that accepts the const parameter, the compiler-generated copy constructor will accept a single parameter of the const type& type. Otherwise, the compiler-generated copy constructor will accept a single parameter of the type& type.
You can use constructors to initialize a const or volatile object, but the constructor itself cannot be declared as const or volatile. The only legitimate storage class for a constructor is inline; using any other storage class modifier (including the __declspec keyword) with the constructor will result in a compiler error. The
StdCall calling convention is used to declare static member functions and global functions using the __stdcall keyword and does not use a variable argument list. When you use the __stdcall keyword for non-static member functions, such as constructors, the compiler uses the thiscall calling convention. The constructor of a
base class is not inherited by a derived class. When an object of a derived class type is created, the object is constructed from the base class component, and then moved to the derived class component. Because a portion of the entire object is initialized, the compiler uses the constructor of each base class (except for virtual derivations, as described in initializing the base class). The
explicitly calls the constructor
to explicitly call a constructor in your program to create an object of a given type. For example, to create a two point object that describes the end of a row, write the following code:
DrawLine (Point (87, 91));
Creates two objects of type point, passes it to the function DrawLine, and destroys it at the end of the expression (function call).
Another context in which the constructor is explicitly called is initializing:
Point pt = Point (7, 11);
Creates and initializes an object of type int using a constructor that accepts two arguments of type point.
Objects created by an explicit call to the constructor, such as the two examples above, are not named, and the object has the lifetime of the expression in which they were created. This is discussed in more detail in the temporary object.
In general, it is safe to call all member functions from within the constructor, because the object is fully set (initialized virtual tables, etc.) before the first line of user code executes. However, it may be unsafe for a member function to call a virtual member function of an abstract base class during construction or destructor.
Constructors can call virtual functions. When a virtual function is invoked, the called function will be a function (or inherit from its base class) that is defined for the constructor's own class. The following example shows what happens when a virtual function is called from within the constructor:
//Specl_calling_virtual_functions.cpp/compile with:/EHsc #include <iostream>
using namespace Std; Class Base {public:base ();
Default constructor. virtual void f ();
Virtual member function.
};
Base::base () {cout << "constructing Base sub-object\n"; f ();
Call virtual member function}//from inside constructor.
void Base::f () {cout << "called Base::f () \ n";} Class Derived:public Base {public:derived ();
Default constructor. void f (); implementation of Virtual};
function F for this class.
Derived::D erived () {cout << "constructing Derived object\n";}
void Derived::f () {cout << "called Derived::f () \ n";}
int main () {Derived D;}
When you run the previous program, declaring Derived D produces the following sequence of events:
invokes the constructor of the class Derived (Derived::D erived).
The constructor of the class Base (Base::base) is invoked before the body of the constructor for the Derived class is entered.
Base::base calls the function f, which is a virtual function. Typically, Derived::f is invoked because object D belongs to the type Derived. Because the Base::base function is a constructor, the object does not belong to the Derived type and the base::f is invoked.