Basic syntax of inheritance
Inheritance: in order to realize the common header and common bottom similar to the website, it is used to avoid code redundancy
Inheritance syntax: class subclass: inheritance method parent class
Alias: the parent class is also called the base class, and the child class is also called the derived class
#include <iostream> using namespace std; // Page header class Head { public: // Constructor Head(){ cout << "This is the page header" << endl; } }; // Page tail class Tail { public: // Constructor Tail() { cout << "This is the end of the page" << endl; } }; // Python page class Python :public Head, public Tail{ public: // Constructor Python() { cout << "Page content loading" << endl; } }; int main() { // Instantiate Python pages Python p1; // outputs: This is the page header // This is the end of the page // Page content loading system("pause"); return 0; }
From the above code, we can also analyze the creation relationship between parent and child classes: the parent class is created first, and the child class is created later
Inheritance mode
There are three ways of inheritance: public inheritance, protected inheritance and private inheritance
Step 1: first create a base class A and perform a simple assignment operation
class A { public: A() { a = 1; b = 2; c = 3; } public: int a; protected: int b; private: int c; };
Step 2: create class B and inherit base class A by public inheritance
// Public attributes and protected attributes are inherited correspondingly, while private attributes cannot be inherited class B :public A { // 1. Attributes inherited from Class A //public: // int a; //protected: // int b; public: // 1. Try to access a and b void func() { cout << a + b << endl; // 3 } // 2. Try to access c //void func() { // cout << c << endl; // Error! //} };
Step 3: create class C and inherit base class A by protecting inheritance
// Public attributes and protection attributes are inherited from corresponding protection attributes, while private attributes cannot be inherited class C :public A { // Attributes inherited from Class A //protected: // int a; // int b; };
Step 4: create class D and inherit base class A by private inheritance
// Both public attributes and protected attributes are inherited corresponding to private attributes, while private attributes cannot be inherited class D :private A { // 1. Attributes inherited from Class A //private: // int a; // int b; public: // 2. Try to access a and b within the class void func() { cout << a + b << endl; // 3 } }; int main() { D d1; d1.func(); // 3. Try to access private member variables outside the class // d1.a = 1; // Error! system("pause"); return 0; }
Object model in inheritance
Question: which members inherited from the parent class belong to the subclass object
Important: all non static member attributes in the parent class are inherited; The private member attribute in the parent class is hidden by the compiler, so it cannot be accessed, but it is inherited
#include <iostream> using namespace std; class Base { public: int a; protected: int b; private: int c; }; class Son :public Base{ public: int d; }; int main() { Son s1; cout << "sizeof of Son = " << sizeof(s1) << endl; // sizeof of Son = 16 system("pause"); return 0; }
You can use the developer command prompt tool to specifically query the model of the class
Step 1: first copy the file path, open the developer command prompt tool, and then cd to this folder
Step 2: type the following command
cl /d1 reportSingleClassLayout Class name file name
Step 4: display the specific model
Tectonic and destructional sequence
After a subclass inherits from the parent class, when a subclass object is created (released), the constructor (destructor) function of the parent class will also be called
Constructor calling order: call the constructor of the parent class first, and then the constructor of the child class
Destructor calling order: call the destructor of the subclass first, and then call the destructor of the parent class
#include <iostream> using namespace std; class Base { public: Base() { cout << "base Object creation completed!" << endl; } ~Base() { cout << "base Object destruction completed!" << endl; } }; class Son :public Base{ public: Son() { cout << "son Object creation completed!" << endl; } ~Son() { cout << "son Object destruction completed!" << endl; } }; void func() { Son s1; } int main() { func(); // outputs:base object creation completed! // son object creation completed! // The object is destroyed! // base object destruction completed! system("pause"); return 0; }
Member processing with the same name
Question: how to access the members in the subclass or parent class through the subclass object when there are members with the same name in the subclass and parent class
Key: you can directly access members of subclasses with the same name; However, when accessing a member with the same name as the parent class, you need to add a scope (if a member function with the same name as the parent class appears in the subclass object, the function with the same name in the subclass will hide all member functions with the same name in the parent class)
#include <iostream> using namespace std; class Base { public: Base() { m_a = 1; } void fun1() { cout << "Base ~ fun1" << endl; } void fun1(int a) { cout << "Base ~ fun1 + " << a << endl; } public: int m_a; }; class Son :public Base{ public: Son() { m_a = 2; } void fun1() { cout << "Son ~ fun1" << endl; } public: int m_a; }; void func() { Son s1; // attribute // 1. Directly output members with the same name in subclasses cout << s1.m_a << endl; // 2 // 2. A member with the same name as the output parent class needs a scope cout << s1.Base::m_a << endl; // 1 // method // 1. Directly output members with the same name in subclasses s1.fun1(); // Son ~ fun1 // 2. A member with the same name as the output parent class needs a scope s1.Base::fun1(); // Base ~ fun1 s1.Base::fun1(100); // Base ~fun1 + 100 } int main() { func(); system("pause"); return 0; }
Static member processing with the same name
Question: how do static members with the same name in inheritance access on subclass objects
Key: you can directly access static members of subclasses with the same name; However, when accessing a static member with the same name as the parent class, you need to add a scope (if a member function with the same name as the parent class appears in the subclass object, the function with the same name in the subclass will hide all member functions with the same name in the parent class)
#include <iostream> using namespace std; class Base { public: static void fun1() { cout << "Base ~ fun1" << endl; } static void fun1(int a) { cout << "Base ~ fun1 + " << a << endl; } public: // Static member definition static int m_a; }; // Static member out of class initialization int Base::m_a = 1; class Son :public Base{ public: static void fun1() { cout << "Son ~ fun1" << endl; } public: static int m_a; }; int Son::m_a = 2; void func() { Son s1; // 1. Access member properties cout << s1.m_a << endl; // 2 cout << s1.Base::m_a << endl; // 1 // 2. Method of accessing members s1.fun1(); // Son ~fun1 s1.Base::fun1(); // Base ~fun1 s1.Base::fun1(2); // Base ~fun1 + 2 } int main() { func(); system("pause"); return 0; }
Multiple inheritance syntax
C + + allows a class to inherit multiple classes
Inheritance syntax: class subclass: inheritance method 1, parent class 1, inheritance method 2, parent class 2
Important: multiple inheritance may cause the occurrence of members with the same name in the parent class, which needs to be distinguished by scope
#include <iostream> using namespace std; class Base1 { public: Base1() { m_a = 1; } int m_a; }; class Base2 { public: Base2() { m_a = 2; } int m_a; }; class Son :public Base1, public Base2{ public: Son() { m_a = 3; } int m_a; }; void func() { Son s1; // Only object properties are used here // 1. Access subclass object properties cout << s1.m_a << endl; // 3 // 2. Access the properties of the parent object through the child object plus scope cout << s1.Base1::m_a << endl; // 1 // 3. Access the properties of the parent object through the child object plus scope cout << s1.Base2::m_a << endl; // 2 } int main() { func(); system("pause"); return 0; }
diamond inheritance
Diamond inheritance concept: two derived classes inherit from a base class, while another class inherits from the two derived classes at the same time
#include <iostream> using namespace std; // Base class class Animal { public: int Age_; }; // Second derived class class Cattle :public Animal{ //public: // int Age_; }; class Horse :public Animal { //public: // int Age_; }; // Base class class CattleHorse :public Cattle, public Horse{ }; int main() { // 1. Instantiate cattle and horses CattleHorse ch; // 2. Assign a value to the Cattle attribute of the parent object through the bull and horse object and add the scope ch.Cattle::Age_ = 20; // 3. Assign a value to the parent object's Horse attribute through the bull and Horse object and add the scope ch.Horse::Age_ = 10; // 4. So the question arises: is the age of Cattle and horses Cattle or Horse cout << ch.Cattle::Age_ << endl; // 20 cout << ch.Horse::Age_ << endl; // 10 system("pause"); return 0; }
Virtual inheritance can solve this problem perfectly
Specific operation means: add the keyword virtual before inheritance to change it into virtual inheritance. The initial base class is called virtual base class
#include <iostream> using namespace std; // Base class class Animal { public: int Age_; }; // Second derived class class Cattle :virtual public Animal{ //public: // int Age_; }; class Horse :virtual public Animal { //public: // int Age_; }; // Base class class CattleHorse :public Cattle, public Horse{ }; int main() { // 1. Instantiate cattle and horses CattleHorse ch; // 2. Assign a value to the Cattle attribute of the parent object through the bull and horse object and add the scope ch.Cattle::Age_ = 20; // 3. Assign a value to the parent object's Horse attribute through the bull and Horse object and add the scope ch.Horse::Age_ = 10; // 4. The age of cattle and horses is the last assignment, ch. horse:: age_= 10; cout << ch.Age_ << endl; // 10 ch.Age_ = 30; cout << ch.Age_ << endl; // 30 system("pause"); return 0; }