The constructor is a special method. It is mainly used to initialize an object when it is created, that is, to assign initial values to object member variables. It is always used with the new operator in the statement that creates an object. A particular class can have multiple constructors, which can be distinguished according to the number of parameters or the type of the parameters, that is, the overload of the constructor. (Taken from Baidu Encyclopedia constructor).
First, the most basic constructor
class Base
{
public:
Base (int var): m_Var (var)
{
}
private:
int m_Var;
};
The execution process of the above constructor:
① Passing parameters
② Open up space for class data members
③ Perform colon syntax to initialize data members
④ execute the contents of the constructor brackets
What needs to be explained here is that the content after the colon syntax is equivalent to int a = 10; (initialization), and the constructor brackets are equivalent to int a; a = 10; (assigning an initial value)
Second, the copy constructor
class Base
{
public:
Base (int var): m_Var (var)
{
}
// Copy constructor
Base (Base & ref): m_Var (ref.m_Var)
{
}
private:
int m_Var;
};
Why can we only use references to the parameters of the copy constructor?
This will start from the time when the copy constructor type is triggered. The following cases will automatically call the copy constructor:
① When initializing a new object with an existing object
② When passing an object to a parameter by value
③ When the function returns an object
So when an object passes a function by passing a value, the copy constructor is automatically called to generate the object in the function. If an object is passed into its own copy constructor, its copy constructor will be called to copy the object so that copy can be passed into its own copy constructor, which will cause an infinite loop until the stack overflows except when the object In addition to being called implicitly when passing in a function, the copy constructor is also called when the object is returned by the function. (Taken from Baidu Encyclopedia copy constructor).
Zh
Copy constructors generally do not need to be written by themselves. The system's default copy constructors can resist it, but in some cases, it is necessary to open up space during construction. At this time, copy constructors are required. A guide to high-quality C ++ programming.
class String
{
public:
String (const char * str = NULL); // ordinary constructor
String (const String & other); // copy constructor
~ String (void); // destructor
private:
char * m_data; // used to save strings
};
// Destructor of String
String :: ~ String (void)
{
delete [] m_data;
// Since m_data is an internal data type, it can also be written as delete m_data;
}
// ordinary constructor for String
String :: String (const char * str)
{
if (str == NULL)
{
m_data = new char [1]; // better if NULL can be added
* m_data = '\ 0';
}
else
{
int length = strlen (str);
m_data = new char [length + 1]; // better if NULL can be added
strcpy (m_data, str);
}
}
// copy constructor
String :: String (const String & other)
{
int length = strlen (other.m_data);
m_data = new char [length + 1]; // better if NULL can be added
strcpy (m_data, other.m_data);
}
Third, the writing of ordinary derived class constructor
When defining a derived class object, the construction operation is performed as follows:
① Passing parameters
② Construct the base class according to the declaration order when inheritance
③ open up space for class data members
④ Execute the statement following the colon syntax
⑤ execute the constructor function body statement
class Base
{
public:
Base (int b): m_b (b)
{
}
private:
int m_b;
};
class Derived: public Base
{
public:
// Writing of ordinary derived class constructor
Derived (int b, int d): Base (b), m_d (d)
{
}
private:
int m_d;
};
Write another example of multiple inheritance:
class Base1
{
public:
Base1 (int b1): m_b1 (b1)
{
}
private:
int m_b1;
};
class Base2
{
public:
Base2 (int b2): m_b2 (b2)
{
}
private:
int m_b2;
};
class Derived: public Base1, public Base2
{
public:
Derived (int b1, int b2, int d): Base1 (b1), Base2 (b2), m_d (d)
{// Note that the order after the colon syntax doesn't matter, the creation of the base class is performed in the order of the inheritance declaration above ...
}
private:
int m_d;
};
Fourth, the writing of derived class constructors with virtual inheritance
Why use virtual inheritance?
Virtual inheritance is mainly aimed at the problem of ambiguity when multiple inheritance occurs. For example, the following code needs to use virtual inheritance. Otherwise, when Derived class inherits, the Base class will be ambiguous.
The implementation of the virtual inheritance constructor is as follows:
① Passing parameters
② Create a base class. Note that at this time, it is necessary to display the creation of all "parameter constructor" base classes, including direct base classes and indirect base classes. Zh
③ open up space for class data members
④ Perform colon syntax
⑤ execute the constructor function body
Note: You may be wondering, does the following code create the Base indirect base class 3 times? In fact, this is not the case. The compiler handles it this way. When the furthest derived class Derived creates the base class Base, the direct base class creation statement of the Base class will be ignored.
class Base
{
public:
Base (int b): m_b (b)
{
}
private:
int m_b;
};
class Base1: virtual public Base
{
public:
Base1 (int b, int b1): Base (b), m_b1 (b1)
{
}
private:
int m_b1;
};
class Base2: virtual public Base
{
public:
Base2 (int b, int b2): Base (b), m_b2 (b2)
{
}
private:
int m_b2;
};
// Virtual inheritance to avoid ambiguity
class Derived: public Base1, public Base2
{
public:
Derived (int b, int b1, int b2, int d): Base (b), Base1 (b, b1), Base2 (b, b2), m_d (d)
{// Note that the order after the colon syntax doesn't matter. Creating the base class is performed in the order of the inheritance declaration above ...
}
private:
int m_d;
};
Fifth, about destructive
Virtual destructor is usually accompanied by polymorphism. The main way of polymorphism is to use the pointer or reference of the base class to point to or reference the derived class, and form polymorphism.
However, there will be a problem. When we destruct, because it is a pointer to the base class, the constructor of the base class will be called, which will cause the derived memory to overflow. To solve this problem, the concept of virtual destruction is introduced. Declare the constructor of the base class as virtual, so that it can accurately call the destructor of the derived class when calling the destructor.
The following code must use virtual destructuring to accurately destruct the derived class and release its occupied memory.
class Base
{
public:
Base (int b): m_b (b)
{
}
// Virtual destructuring, so that the base class pointer can accurately release the contents of the derived class pointed to
virtual ~ Base ()
{
}
private:
int m_b;
};
class Derived: public Base
{
public:
Derived (int b, char * pStr): Base (b)
{
m_pStr = new char [strlen (pStr) +1];
strcpy (m_pStr, pStr);
}
~ Derived ()
{
delete m_pStr;
m_pStr = NULL;
}
private:
char * m_pStr;
};
int main (void)
{
char * pStr = "abcdefg";
Base * b = new Derived (1, pStr);
delete b;
return 0;
}
————————————————
Copyright statement: This article is the original article of the CSDN blogger "qingdujun", which follows the CC 4.0 BY-SA copyright agreement.
Original link: https://blog.csdn.net/qingdujun/article/details/38617035