01 member objects and closed classes
If there are other objects in a class, the object is called a member object; if there are member objects, the class is called a closed class;
class CTyre // Tyres { public: // Parametered constructor // Initializing member variables m radius and m width CTyre(int r, int w):m_radius(r),m_width(w) { } private: int m_radius; // radius int m_width; // width }; class CEngine // Engine class { // There will be parameterless constructors by default }; class CCar // Automobile class closed class { public: // Parametered constructor // Initialize the member variable m ﹐ price and the member object tyre CCar(int p, int tr, int tw):m_price(p),tyre(tr,tw){} private: int m_price; // Price CTyre tyre; // member object CEngine engine; // member object }; int main() { CCar car(10000,20,50); return 0; }
In the above example, if the CCar class does not define a constructor, the default parameterless constructor will be used, and the following statement will compile with errors:
CCar car;
Because the compiler doesn't understand how to initialize the type member object in the CCar class. The initialization of the engine member object is OK, because the default constructor is OK.
Any statements that generate closed class objects should make the compiler understand how the member objects in the objects are initialized.
The specific way is to close the initialization list of the constructor of the class.
02 execution order of closed class constructors and destructors
- When closed class objects are generated, the constructors of all member objects are executed first, and then the constructors of closed classes are executed.
- The constructor execution order of the member object is the same as that of defining the member object in the enclosing class.
- When the object of a closed class is busy, you only need to remember one sentence: first construct the object, then construct it. Because the closed class is constructed last, the closed class object is constructed first.
class CTyre // Tyres { public: CTyre(){ std::cout << "CTyre Constructor" << std::endl; } ~CTyre(){ std::cout << "CTyre Destructor" << std::endl; } }; class CEngine // Engine class { public: CEngine(){ std::cout << "CEngine Constructor" << std::endl; } ~CEngine(){ std::cout << "CEngine Destructor" << std::endl; } }; class CCar // Automobile class -- 3. Finally construct closed class object { public: CCar(){ std::cout << "CCar Constructor" << std::endl; } ~CCar(){ std::cout << "CCar Destructor" << std::endl; } private: CTyre tyre; // 1. Construct the member object first CEngine engine; // 2. Then construct the member object }; int main() { CCar car; return 0; }
Execution result:
CTyre constructor CEngine constructor CCar constructor CCar destructor CEngine destructor CTyre destructor
03 copy constructor of enclosing class
class A { public: // Parameterless constructor A() { std::cout << "A Constructor" << std::endl; } // copy constructor A(A & a) { std::cout << "A copy constructor " << std::endl; } }; class B { // If the constructor and copy constructor are not declared, the compiler will generate the constructor and copy constructor by default A a; // member object }; int main() { B b1; // Both the b1 object and the member object a execute parameterless constructors B b2(b1); // Both the b2 object and the member object a perform the copy constructor return 0; }
Output results:
A constructor A copy constructor