C + + core Article 8 and object inheritance

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;
}

Tags: C++ Back-end

Posted on Sat, 23 Oct 2021 01:08:59 -0400 by Romeo20