[C++] Learning to inherit this one is enough! 【Graphic + Code】

 

An article takes you to understand inheritance.

C++ inheritance

  • Preface
  • 1. The concept of inheritance
    • 1. Inheritance definition 
    • 2. Inheritance and access qualifiers
    • 3. Base class and derived class object assignment conversion
    • 4. Scope in inheritance
    • 5. The default member function of the derived class
    • 6. Inheritance and Friends
    • 7. Inheritance and static members
  • to sum up

 


Preface

Everything in the world will have an inheritance system, it will more or less inherit certain characteristics of the parent class, such as people, animals, etc., then our code will also have this characteristic, let us take a look Put


Tip: The following is the content of this article.

1. Inheritance

The inheritance mechanism is the most important means of object-oriented programming to make code reusable. It allows programmers to expand and increase functions while maintaining the original characteristics of the class, thus generating new classes, which are called derived classes. Inheritance presents the hierarchical structure of object-oriented programming and embodies the cognitive process from simple to complex. In the past, the reuse we touched was all function reuse, and inheritance was the reuse of the class design level. .

1. Inheritance definition 

Let's look at the picture below.

We are looking at the code

class Base
{
public:
	void fun()
	{
		cout << "Base::fun()" << endl;
	}
};
// 子类          父类
class D :public Base  //  继承
{
public:
	void show()
	{
		cout << "D::shoe()" << endl;
	}
};
void main()
{
	D d;
	d.show();
	d.fun();//  子类可以访问父类的信息
}

 2. Inheritance and access qualifiers

 

3. Assignment conversion of base class and derived class object

Derived class objects can be assigned to base class objects/base class pointers/base class references. There is an image here called slicing or cutting. The implication is to cut the parent class in the derived class and assign it to the past.
Base class objects cannot be assigned to derived class objects意思就是子类可以给父类赋值,父类不能给子类赋值

 Let's take a look at the code ( there are detailed comments in the code )

class Person
{
public:
	void Print()
	{
		cout << "name" << _name << endl;
		cout << "age:" << _age << endl;
	}
protected:
	string _name = "peter"; // 姓名
	int _age = 18; // 年龄
};
class Teacher : public Person
{
protected:
	int _stuid; // 学号
};
void main()
{
	Teacher tcher;  //首先他有一个 _name  _age  _stuid 成员
	Person per;  //  _name  _age 成员
	//  因为tcher 中包含有per的所有成员   所以子类就可以给父类赋值  而父类不可以给子类赋值 
	//所以我们将子类就可以给父类赋值的这种现象叫  对象的切片
}

4. Scope in inheritance

  1.  In the inheritance system, the base class and the derived class have independent scopes .
  2.  There are members with the same name in the subclass and the parent class. The subclass members will block the direct access of the parent class to the members with the same name. This situation is called hiding or redefinition . (In the subclass member function, you can use the base class :: base class member display access)
  3.  It should be noted that if it is the hiding of member functions, only the function name is the same to form hiding.
  4.  Note that in practice, it is best not to define members with the same name in the inheritance system.

 

 

 What is hidden by the same name, let’s take a look at the code

class Base
{
public:
	void fun()
	{
		cout << "Base::fun()" << endl;
	}
};
// 子类          父类
class D :public Base  //  继承
{
public:
	void fun()
	{
		cout << "D::fun()" << endl;
	}
	void show()
	{
		cout << "D::shoe()" << endl;
	}
};
void main()
{
	D d;
	Base *pb = &d;
	pb->fun();//  只能访问子类中父类所有的fun函数
	d.fun();  //  只能访问子类自己的fun函数
}

 

It can be seen from the above code that the subclass accesses its own fun function. Originally, the subclass can access the fun function of the parent class, but because the subclass also has the same function with the same name as the parent class, the parent class is hidden. This is called hiding with the same name

It is equivalent to that when the child does not have a house, he can live in his father’s house, but when the child has a house, he cannot live in the parent’s house and must live in his own house .

5. The default member function of the derived class

  1. The constructor of the derived class must call the constructor of the base class to initialize that part of the members of the base class. If the base class does not have a default constructor, the call must be displayed during the initialization list stage of the derived class constructor.
  2.  The copy constructor of the derived class must call the copy constructor of the base class to complete the copy initialization of the base class.
  3.  Operator= of the derived class must be called operator= of the base class to complete the copy of the base class.
  4.  The destructor of the derived class will automatically call the destructor of the base class to clean up the members of the base class after being called. Because this is the way to ensure that the derived class objects first clean up the derived class members and then clean up the order of the base class members.
  5.  The initialization of the derived class object first calls the base class structure and then calls the derived class structure.
  6.  Derived class object destruction cleanup first call the derived class destruction and then adjust the base class destruction

The six default member functions of the class are the constructor, the copy constructor, the destructor, the assignment operator overload, the address operator overload, and the const modified address operator overload .

In the inheritance relationship, if the six default constructors are not explicitly defined in the derived class, the compiler system will synthesize these six member functions by default.

Let's write the code to take a look ( there are detailed comments in the code )

class Base
{
public:
	Base()
	{
		cout << "Base::Base()" << endl;
	}
	Base(const Base &b)//  拷贝构造
	{
		cout << "Base::Base(const Base &)" << endl;
		m_b = b.m_b;
	}
	Base operator=(const Base &b)//赋值语句
	{
		cout << "Base operator=(const Base &b)" << endl;
		m_b = b.m_b;
		return *this;
	}
public:
	void fun()
	{
		cout << "Base::fun()" << endl;
	}
	void fun(int a)
	{
		cout << "Base::fun(int a)" << endl;
	}
private:
	int m_b;
};
// 子类          父类
class D :public Base  //  继承
{
public:
	D() :m_b(0)  // 会调用父类的构造方法 但是如果父类构造方法给一个 Base(int b):m_b(b) 就不能成功了 因为父类要求是一个有参的  所以在参数列表改为 D():m_b(0),Base(0)
	{

	}

public:
	void fun()
	{
		cout << "Base::fun()" << endl;
	}
	void show()
	{
		cout << "D::shoe()" << endl;
	}
private:
	int m_b;
};
void main()
{
	D d;
	D d1 = d;//  调用的是父类的拷贝构造方法  说明我们在完成子类的拷贝构造当中首先要拷贝构造的是父类对象
	D d2;
	d2 = d1;
}

The results are as follows: 

We can see:

In fact, the compiler first enters the constructor of the derived class, then calls the constructor of the base class in the initialization list, and then comes back to execute its own function body.

6. Inheritance and Friends

The friendship relationship cannot be inherited, which means that the base class friends cannot access the private and protected members of the subclass

Specifically, let's take a look at the code ( there are detailed comments in the code )

//友元关系不能继承,也就是说基类友元不能访问子类私有和保护成员  如下
class Student;
class Person;
void Display(const Person& p, const Student& s);
class Person
{
public:
	friend void Display(const Person& p, const Student& s);
protected:
	string _name = "cb"; // 姓名
};
class Student : public Person
{

protected:
	int _stuNum = 418; // 学号
};
void Display(const Person& p, const Student& s)
{
	cout << p._name << endl;
	cout << s._stuNum << endl;// 之所以不能访问就是因为这仅仅是父类的友元函数 子类不能访问
	// 要怎末才能访问  就只能形成自己的友元函数  在子类中在加一句friend void Display(const Person& p, const Student& s);
	//  相当于爸爸的朋友不见得是儿子的朋友  儿子要操作只能自己在声明交朋友形成友元函数
}
void main()
{
	Person p;
	Student s;
	Display(p, s);
}

The above code shows that friends are just like friends. Friends of the parent category are not necessarily friends of the child category. Friends of the same child category are not necessarily friends of the parent category. Therefore, when you want to visit someone, you must declare who Whose friend is, you can only access its private or protected members after it is declared.

 

  1. There is no transitivity in the friend relationship, that is, each class is responsible for controlling its own friend class or friend function ;
  2. The friendship relationship is one-way and not interchangeable. If class B is a friend of class A, class A is not necessarily a friend of class B, depending on whether there is a corresponding declaration in the class.
  3. Friendship cannot be inherited.

7. Inheritance and static members

The base class defines static static members, and there is only one such member in the entire inheritance system. No matter how many subclasses are derived, there is only one static member instance.

Similarly, we look at the code as follows:

//继承与静态成员
//基类定义了static静态成员,则整个继承体系里面只有一个这样的成员。无论派生出多少个子类,都只有一个static成员实例 。如下
class Test
{
public:
	Test()
	{
		count++;
	}
public:
	int GetCount()const
	{
		return count;
	}
	//int GetCount()const
	//{
	//	return GetOBJCount();
	//}
private:
	static int count;//  类的静态成员必须在类外初始化
                     //因为静态成员属于整个类,而不属于某个对象,如果在类内初始化,会导致每个对象都包含该静态成员,这是矛盾的
};
int Test::count = 0;
class D1 :public Test
{
public:
	//int GetCount()const
	//{
	//	return GetOBJCount();
	//}
};
class D2 :public Test
{
public:
	//int GetCount()const
	//{
	//	return GetOBJCount();
	//}
};
class D3 :public Test
{
public:
	//int GetCount()const
	//{
	//	return GetOBJCount();
	//}
};
class D4 :public Test
{
public:
	//int GetCount()const
	//{
	//	return GetOBJCount();
	//}
};
void main()
{
	D1 d1;
	cout << d1.GetCount() << endl;
	D2 d2;
	cout << d2.GetCount() << endl;
	D3 d3;
	cout << d3.GetCount() << endl;
	D4 d4;
	cout << d4.GetCount() << endl;
}

Through the above code, it is not difficult to see:

The base class defines static static members, and there is only one such member in the entire inheritance system. No matter how many subclasses are derived, there is only one static member instance .

Static modified members can only be declared in the class and defined outside the class . The reason is that static members belong to the entire class and not to an object . If initialized in the class, each object will contain the static member. This is contradictory.

to sum up

Public inheritance is an is-a relationship. In other words, each derived class object is a base class object.

Combination is a has-a relationship. Suppose B combines A, and there is an A object in each B object.

Here also need to talk about  multiple inheritance issues involving complex issues such as diamond inheritance. (There will be a detailed introduction in the blog class later)

Thank you for reading, if there are any errors, please correct me! ! !

 

 

 

 

 

 

 

Guess you like

Origin blog.csdn.net/qq_45615577/article/details/115291235