C++ study notes 18-classes and objects-inheritance

18.0 Preface

Inheritance is one of the three characteristics of object-oriented .
There is a special relationship between some classes, such as the figure below:
insert image description here
We found that when defining these classes, members of the lower level not only have the commonality of the upper level, but also have their own characteristics.

At this time, we can consider using inheritance techniques to reduce duplication of code .


18.1 Basic Syntax of Inheritance

For example, we see that many websites have a common header, a common bottom, and even a common left list, only the center content is different.

Next, we use the common writing method and the inherited writing method to realize the content in the web page, and see the meaning and benefits of inheritance.

grammar:

class 子类:继承方式 父类 
  • Benefits of Inheritance: Less Reissued Code
  • Subclasses are also known as derived classes
  • The parent class also becomes the base class

Example:

#include<iostream>
using namespace std;

//普通方法实现网络页面
//Java
class Java
{
    
    
public:
	Java()
	{
    
    
		this->header();
		this->footer();
		this->left();
		this->content();
	}
	void header()
	{
    
    
		cout << "首页、公开课、登录、注册、...(公共头部)" << endl;
	}
	void footer()
	{
    
    
		cout << "帮助中心、交流合作、站内地图...(公共底部)" << endl;
	}
	void left()
	{
    
    
		cout << "Java、Python、C++、...(公共分类列表)" << endl;
	}
	void content()
	{
    
    
		cout << "Java学科视频" << endl;
	}
};
void test1_01()
{
    
    
	cout << "Java下载视频页面如下:" << endl;
	Java ja;
}
//Python
class Python
{
    
    
public:
	Python()
	{
    
    
		this->header();
		this->footer();
		this->left();

	}
	void header()
	{
    
    
		cout << "首页、公开课、登录、注册、...(公共头部)" << endl;
	}
	void footer()
	{
    
    
		cout << "帮助中心、交流合作、站内地图...(公共底部)" << endl;
	}
	void left()
	{
    
    
		cout << "Java、Python、C++、...(公共分类列表)" << endl;
	}
	void content()
	{
    
    
		cout << "Python学科视频" << endl;
	}
};
void test1_02()
{
    
    
	cout << "Python下载视频页面如下:" << endl;
	Python py;
}

//继承方法实现网络页面
//C++
class BasePage
{
    
    
public:
	BasePage()
	{
    
    
		this->header();
		this->footer();
		this->left();
	}
	void header()
	{
    
    
		cout << "首页、公开课、登录、注册、...(公共头部)" << endl;
	}
	void footer()
	{
    
    
		cout << "帮助中心、交流合作、站内地图...(公共底部)" << endl;
	}
	void left()
	{
    
    
		cout << "Java、Python、C++、...(公共分类列表)" << endl;
	}
};

//继承的好处:减少重发代码
//语法:class 子类:继承方式 父类
//子类也称为派生类
//父类也成为基类
class Cpp:public BasePage
{
    
    
public:
	Cpp()
	{
    
    
		this->content();
	}
	void content()
	{
    
    
		cout << "C++学科视频" << endl;
	}
};

void test1_03()
{
    
    
	cout << "C++下载视频页面如下:" << endl;
	Cpp cpp;
}

int main()
{
    
    
	test1_01();
	cout << "----------------" << endl;
	test1_02();
	cout << "----------------" << endl;
	test1_03();
	system("pause");
	return 0;
}

The members in the derived class include two parts:
one is inherited from the base class, and the other is the added members.
Inherited from the base class shows its generality, while the newly added members show its individuality.


18.2 Inheritance method

There are three types of inheritance:

  • public inheritance
  • protected inheritance
  • private inheritance

insert image description here

Example:

#include<iostream>
using namespace std;
//继承方式

//公共继承
class Base1 
{
    
    
public:
	int m_A;
protected:
	int m_B;
private:
	int m_C;
};
class Son1 :public Base1
{
    
    
public:
	void func()
	{
    
    
		m_A = 10;	//父类中的公共权限成员,到子类依旧是公共权限成员
		m_B = 10;	//父类中的保护权限成员,到子类依旧是保护权限成员
		//m_C = 10; //父类中的私有权限成员,子类无法访问
	}
};
void test2_01()
{
    
    
	Son1 s1;
	s1.m_A = 100;
	//s1.m_B = 100; //保护权限,访问不到
}

//保护继承
class Son2 :protected Base1
{
    
    
public:
	void func()
	{
    
    
		m_A = 100;  //父类中的公共权限成员,到子类中变成了保护权限成员
		m_B = 100;	//父类中的保护权限成员,到子类中依旧是保护权限成员
		//m_C = 100;//父类中的私有权限成员,子类无法访问
	}
};
void test2_02()
{
    
    
	Son2 s2;
	//s2.m_A = 100; //保护权限,访问不到
	//s2.m_B = 100; //保护权限,访问不到
}

//私有继承
class Son3 :private Base1
{
    
    
public:
	void func()
	{
    
    
		m_A = 100;  //父类中的公共权限成员,到子类中变成了私有权限成员
		m_B = 100;	//父类中的保护权限成员,到子类中变成了私有权限成员
		//m_C = 100;//父类中的私有权限成员,子类无法访问
	}
};
//可以通过再创建一个类来继承此类查看成员是否为私有权限
class GrandSon3 :public Son3
{
    
    
public:
	void func()
	{
    
    
		//m_A = 100;//父类中的私有权限成员,子类无法访问
		//m_B = 100;//父类中的私有权限成员,子类无法访问
	}
};

int main()
{
    
    
	system("pause");
	return 0;
}

18.3 Object Models in Inheritance

18.3.1 Subclass inherits all parent class members

Question: Which of the members inherited from the parent class belong to the subclass object?

Answer: All non-static member properties in the parent class will be inherited by the subclass.

#include<iostream>
using namespace std;

//继承中的对象模型
class Base
{
    
    
public:
	int m_A;
protected:
	int m_B;
private:
	int m_C; //私有成员属性被编译器隐藏了,只是访问不到,但是确实被继承了
};

class Son :public Base
{
    
    
public:
	int m_D;
};

void test3_01()
{
    
    
	//父类中的所有非静态成员属性都会被子类继承下去
	cout << "size of Son = " << sizeof(Son) << endl;
}

int main()
{
    
    
	test3_01();
	system("pause");
	return 0;
}
  1. Viewing the Object Model Using the Developer Command Prompt Tool

insert image description here
2. Jump to the drive letter E: (the drive letter where the cpp is located)
3. Jump to the file path cd the folder path where the cpp is located
4. View the command cl [filename].cpp /d1reportSingleClassLayoutXXX where XXX is the class name.
as the picture shows:
insert image description here

It can be seen that all non-static member properties in the parent class will be inherited by the subclass.

18.3.2 The parent class pointer points to the subclass object

C++ supports type conversion between parent class and subclass, and the pointer of the parent class can directly point to the subclass object. If the parent class pointer is used to point to the subclass object, then the subclass object will become a parent class object, which will lose its original members and have the members of the parent class, which is equivalent to type conversion.

Example:

#include<iostream>
using namespace std;

//动物类
class Animal
{
    
    
public:
	void speak()
	{
    
    
		cout << "动物在说话" << endl;
	}
};
class Cat :public Animal
{
    
    
public:
	void speak()
	{
    
    
		cout << "小猫在说话" << endl;
		m_A = 100;
	}
};

//执行说话的函数
void doSpeak(Animal& animal) //Animal& animal = cat; 传入的是子类,用父类接收,此时此对象转换为了父类
{
    
    
	cout << (typeid(animal).name()) << endl;
	animal.speak();
	//cout << animal.m_A << endl;  变成了父类对象,没有了子类的成员。
}

void test3_02()
{
    
    
	Cat cat;
	Animal an;
	doSpeak(cat);
}
int main()
{
    
    
	test3_02();
	system("pause");
	return 0;
}

18.4 Construction and destruction order in inheritance

After the subclass inherits the parent class, when the subclass object is created, the constructor of the parent class will also be called.

Question: Who comes first in the order of construction and destruction of the parent class and the subclass?
Answer: The parent class is constructed first, then the subclass is constructed, and the order of destruction is opposite to the order of construction (stack: first in, last out).

Example:

#include<iostream>
using namespace std;
class Base4
{
    
    
public:
	Base4()
	{
    
    
		cout << "Base4构造函数" << endl;
	}
	~Base4()
	{
    
    
		cout << "Base4析构函数" << endl;
	}
};
class Son :public Base4
{
    
    public:
	Son()
	{
    
    
		cout << "Son构造函数" << endl;
	}
	~Son()
	{
    
    
		cout << "Son析构函数" << endl;
	}
};
void test4_01()
{
    
    
	Son son;
}
int main()
{
    
    
	test4_01();
	system("pause");
	return 0;
}

18.5 Inheritance of members with the same name

Question: When there are members with the same name in the subclass and the parent class, how to access the data with the same name in the subclass or parent class through the subclass object?

  • To access the members of the subclass with the same name, you can directly access them. grammar:对象.成员
  • To access members with the same name of the parent class, you need to add a scope. grammar:对象.父类::成员

Let me talk about it here: When a subclass inherits the parent class, the subclass already has all the member variables and member functions of the parent class.

Member variable :

  1. If there is no member variable with the same name as the parent class in the subclass, then the subclass and the parent class share a member variable at this time , and the syntax for accessing this member outside the class is: 对象.成员变量or 对象.父类::成员变量.
  2. In order to distinguish the member variables with the same name in the subclass and the parent class , in the subclass, when you want to access the member variables of the parent class, use the syntax: 父类::成员变量or this->父类::成员变量. Access the member variables of the subclass outside the class : 对象.成员变量; access the member variables of the parent class对象.父类::成员变量 : .

Member function :

  1. If there is no member function with the same name as the parent class in the subclass, then the subclass and the parent class share a member function at this time , use 对象.成员函数or 对象.父类::成员函数.
  2. The member function with the same name in the subclass will hide all the member functions with the same name in the parent class (all overloaded functions with the same name will be hidden) , and you must use the scoped syntax to call the parent class function with the same name.
  3. In short, in a subclass, when you want to call a member function of the parent class, use the syntax: 父类::成员函数or this->父类::成员函数. Call the member function of the subclass outside the class : 对象.成员函数; Call the member function of the parent class : 对象.父类::成员函数.

Example:

#include<iostream>
using namespace std;

class Base5
{
    
    
public:
	Base5()
	{
    
    
		m_A = 100;
	}
	void func()
	{
    
    
		cout << "Base5-func()调用" << endl;
	}
	void func(int a)
	{
    
    
		cout << "Son5_01-func(int a)调用" << endl;
	}
	int m_A;
};
class Son5_01 :public Base5
{
    
    
public:
	Son5_01()
	{
    
    
		m_A = 300;
	}
	//int m_A;   //如果不创建m_A的成员变量,那么构造函数将直接对父类中的m_A进行赋值.
	void func()
	{
    
    
		cout << "Son5_01-func()调用" << endl;
	}

};
class Son5_02 :public Base5
{
    
    
public:
	Son5_02()
	{
    
    	
		//Base5::m_A = 50;  //如果需要改变父类的成员变量,指明作用域即可.
		m_A = 200;
	}
	void funcc()
	{
    
    
		Base5::func();  //在子类中调用父类函数
	}
	int m_A;   //创建m_A的成员变量后,则是对自己的成员m_A进行赋值.
};


void test5_01()
{
    
    
	Son5_01 son;
	cout << "Son5_01下: m_A = " << son.m_A << endl;
	cout << "Base5下: m_A = " << son.Base5::m_A << endl;
}
void test5_02()
{
    
    
	Son5_02 son;
	cout << "Son5_02下: m_A = " << son.m_A << endl;
	cout << "Base5下: m_A = " << son.Base5::m_A << endl;
}


void test5_03()
{
    
    
	cout << "在类外中调用子类和父类函数" << endl;
	Son5_01 son;
	son.func();
	//son.func(100); 父类中的同名成员函数都被隐藏了.
 	son.Base5::func();
 	son.Base5::func(100);
}
void test5_04()
{
    
    
	cout << "在子类中调用父类函数" << endl;
	Son5_02 son;
	son.funcc();
}
int main()
{
    
    
	test5_01();
	test5_02();
	test5_03();
	test5_04();
	system("pause");
	return 0;
}

18.6 Inheritance of static members with the same name

Question: How can static members with the same name in inheritance be accessed on subclass objects?

Static members and non-static members with the same name are handled in the same way.

  • To access the members of the subclass with the same name, you can directly access them. grammar:对象.成员
  • To access members with the same name of the parent class, you need to add a scope. grammar:对象.父类::成员

Note: When accessing parent class members
by class name子类::父类::成员 , the syntax is: .

Example:

#include<iostream>
using namespace std;

class Base6
{
    
    
public:
	static int m_A; //类内定义
	static void func()
	{
    
    
		cout << "Base6-static void func()" << endl;
	}
};
int Base6::m_A=100;//类外初始化
class Son6 :public Base6
{
    
    
public:
	static int m_A;
	static void func()
	{
    
    
		cout << "Son6-static void func()" << endl;
	}
};
int Son6::m_A = 200;

void test6_01()
{
    
    
	//通过对象访问
	cout << "通过对象访问" << endl;
	Son6 s;
	cout << "Son6下的m_A为:" << s.m_A << endl;
	cout << "Base6下的m_A为:" << s.Base6::m_A << endl;
	//通过类名访问
	cout << "通过类名访问" << endl;
	cout << "Son6下的m_A为:" << Son6::m_A << endl;
	cout << "Base6下的m_A为:" << Son6::Base6::m_A << endl;//第一个::代表通过类名访问,第二个::代表作用域
}

void test6_02()
{
    
    
	//通过对象访问
	cout << "通过对象访问" << endl;
	Son6 s;
	s.func();
	s.Base6::func();
	//通过类名访问
	cout << "通过类名访问" << endl;
	Son6::func();
	Son6::Base6::func();
}
int main()
{
    
    	
	test6_01();
	test6_02();

	system("pause");
	return 0;
}

18.7 Multiple inheritance syntax

C++ allows a class to inherit from multiple classes

grammar:

class 子类 : 继承方式 父类1 , 继承方式 父类2 ...{
    
    };

Multiple inheritance may cause members with the same name to appear in the parent class, which needs to be distinguished by scope.

It is not recommended to use multiple inheritance in the actual development of C++.

#include<iostream>
using namespace std;

class Base7_01
{
    
    
public:
	Base7_01()
	{
    
    
		m_A = 100;
	}
	int m_A;
};
class Base7_02
{
    
    
public:
	Base7_02()
	{
    
    
		m_A = 200;
	}
	int m_A;
};
class Son7 :public Base7_01, public Base7_02
{
    
    
public:
	Son7()
	{
    
    
		m_C = 300;
		m_D = 400;
	}
	int m_C;
	int m_D;
};

void test7_01()
{
    
    
	Son7 s;
	cout << "sizeof s = " << sizeof(s) << endl;  //4*4
	cout << "Base7_01的m_A = " << s.Base7_01::m_A << endl;
	cout << "Base7_02的m_A = " << s.Base7_02::m_A << endl;
}

int main()
{
    
    
	test7_01();
	system("pause");
	return 0;
}

18.8 Diamond Inheritance (Diamond Inheritance)

Diamond inheritance concept:

  • Two derived classes inherit from the same base class,
  • Another class inherits these two derived classes at the same time,
  • This type of succession is known as diamond succession, or diamond succession.

Typical Diamond Inheritance Case:
insert image description here
Diamond Inheritance Problem:

  1. Sheep inherit the data of animals, and camels also inherit the data of animals. When the grass mud horse uses the data, there will be ambiguity (using scope to resolve).
  2. The grass mud horse inherits two copies of the data of the animal. In fact, we should be clear that we only need one copy of this data (virtual inheritance solves it).

Virtual inheritance: virtualAfter adding keywords before inheritance, it becomes virtual inheritance.

grammar:

class 子类 : virtual 权限 父类{
    
    };

Example:

#include<iostream>
using namespace std;

//动物
class Animal
{
    
    
public:
	int m_Age;
};

//利用虚继承 解决菱形继承的问题
// //继承之前加上关键字 virtual 变为虚继承
// Animal类称为 虚基类
//羊
class Sheep :virtual public Animal
{
    
    };
//骆驼
class Tuo :virtual public Animal
{
    
    };
//羊驼
class SheepTuo :public Sheep, public Tuo 
{
    
    };

void test8_01()
{
    
    
	SheepTuo st;
	//st.m_Age = 18; 不明确
	st.Sheep::m_Age = 18;
	st.Tuo::m_Age = 28;
	st.m_Age = 100;
	//当菱形继承,两个父类拥有相同数据,需要加以作用域区分
	cout << "st.Sheep::m_Age = " << st.Sheep::m_Age << endl;
	cout << "st.Tuo::m_Age = " << st.Tuo::m_Age << endl;
	cout << "sizeof(st) = " << sizeof(st) << endl;
}
int main()
{
    
    
	test8_01();
	system("pause");
	return 0;
}

When multiple subclasses inherit the parent class using virtual inheritance, the common parent class at this time is called: virtual base class . At this time, there is only one member variable in these classes with inheritance relationship, so it is a member variable whether it is used or
not when accessing . Virtual inheritance is to store a virtual base class pointer in the subclass - vbptr (virtual base pointer), this pointer points to a virtual base class table - vbtable (virtual base table). An offset is stored for each subclass in the virtual base class table. When each subclass accesses member variables, accessing the offset in the virtual base class table through this virtual base class pointer will access the virtual base class. The only member variable.对象.成员对象.父类::成员

insert image description here

Guess you like

Origin blog.csdn.net/qq_49030008/article/details/123321914
Recommended