c + + Lesson 7 - inheritance and derivation

Posted by eazyefolife on Sat, 05 Feb 2022 04:36:25 +0100

Inheritance mode and authority

  • Writing of inheritance:
  • The parent class is also called the base class; Subclasses are also called derived classes
  • The essence of inheritance: there is one copy of the data and member subclasses of the parent class
  • Permission problem: the inheritance method will only enhance the permission display of parent class attributes in subclasses
class Subclass: inheritance method parent class

 

#include <iostream>
#include <string>
using namespace std;
//Parent class
class parent
{
public:
	int a;
    //Interface
    int& getNum()
    {
        return c;
    }
protected:
	int b;
private:
	int c;
};
//public inheritance 
class son1 :public parent
{
public:
	void func()
	{
		a = 10;//Public permission members in the parent class are still public permissions in the child class
		b = 20;//The protection permission member in the parent class is still the protection permission in the child class
		//c = 30;// The private permission member in the parent class cannot be accessed by the child class

	}
};
//Protect inheritance
class son2 :protected parent
{
public:
	void func()
	{
		a = 100;//The public permission member in the parent class and the protection permission in the child class
		b = 200;//The protection permission member in the parent class is still the protection permission in the child class
		//c = 30;// The private permission member in the parent class cannot be accessed by the child class
        //However, private data can be accessed through the interface
        cout<<getNum()<<endl;
	}
};
//Private inheritance
class son3 :private parent
{
public:
	void func()
	{
		a = 1000;//Public permission members in the parent class and private permissions in the child class
		b = 2000;//The protection permission member in the parent class is private permission in the child class
		//c = 30;// The private permission member in the parent class cannot be accessed by the child class
	}
};
//grandson
class GrandSon :public son3
{
public:
	void func()
	{
		//a = 10000;// In son3, a and b become private, and even sons cannot access them
		//b = 20000;
	}
};
void test1()
{
	son1 s1;
	s1.a = 10;
	//s1.b = 20;// In son1, B is not accessible outside the protection permission class
}
void test2()
{
	son2 s2;
	//s2.a = 10;// In son2, a is not accessible outside the protection permission class
	//s1.b = 20;// In son2, B is not accessible outside the protection permission class
}
void test3()
{
	son3 s3;
	//s3.a = 10;// In son2, a is a private permission. It cannot be accessed outside the class
	//s3.b = 20;// In son2, B is a private permission. It cannot be accessed outside the class
}
int main()
{
	return 0;
}
  • The members in a derived class include two parts: ① one is inherited from the base class, and the other is the members added by itself; ② the members inherited from the base class show their commonness, and the new members reflect their individuality
  • Benefits of inheritance: reduce duplicate code
  • All non static member properties of the parent class will be inherited by the child class. The private member properties in the parent class are hidden by the compiler, so they cannot be accessed, but they are indeed inherited

① Open the "Developer Command Prompt for VS2019" tool ② enter the path where the "cd" file is located ③ enter "dir" ④ enter "cl /d1 reportSingleClassLayout subclass name. cpp file name" to view it

 

class A
{
public:
	int a;
protected:
	int b;
private:
	int c;
};
class B : public  A
{
public:

protected:
	int d;
};

cout << sizeof(B) << endl;//Output result: 16
#include <iostream>
#include <string>
using namespace std;
//Parent class
class Common
{
public:
	void header()
	{
		cout << "Home page, open class, login, registration...(Common head)" << endl;
	}
	void footer()
	{
		cout << "Help center, communication and cooperation, station map...(Common (bottom)" << endl;
	}
	void left()
	{
		cout << "Java,Python,C++,...(Public classification list)" << endl;
	}
};
class Java :public Common
{
public:
	void content()
	{
		cout << "Java Subject video"<<endl;
	}
};
class Python :public Common
{
public:
	void content()
	{
		cout << "Python Subject video" << endl;
	}
};
void test1()
{
	cout << "Java The download video page is as follows:" << endl;
	Java ja;
	ja.header();
	ja.footer();
	ja.left();
	ja.content();
}
void test2()
{
	cout << "Python The download video page is as follows:" << endl;
	Python py;
	py.header();
	py.footer();
	py.left();
	py.content();
}
int main()
{
	test1();
	test2();
	return 0;
}

 

Constructor in inheritance

  • The properties of the parent class are initialized by the constructor of the parent class
  • The constructor in the subclass must call the constructor of the parent class and must initialize the parameter list
  • Single inheritance and multiple inheritance

Single inheritance: only one parent class; multiple inheritance: two or more parent classes

  • Inherited attributes always exist no matter how many times they are inherited, so classes will not inherit many layers, which will lead to bloated classes
  • Construction and deconstruction order in inheritance:

Single inheritance: construct the parent class first and then the child class. The order of deconstruction is opposite to that of construction

Multiple inheritance: the construction order is consistent with the inheritance order, but the deconstruction is opposite; Any construction order problem has nothing to do with the initialization parameter list

//Inherited properties are always present
class A
{
public:
	A(int a):a(a){}
	int a;
};

class B:public A
{
public:
	B(int a,int b) :A(a),b(b){}
	int b;
};

class C:public B
{
public:
	C(int a,int b,int c):B(a,b),c(c) {}
	int c;
};

class D :public C
{
public:
	D(int a, int b, int c,int d) :C(a,b,c), d(d) {}
	int d;
};
//Single inheritance
#include <iostream>
#include <string>
using namespace std;
//Parent class
class Parent
{
public:
	Parent() { cout << "Parent class parameterless constructor" << endl; }
	Parent(string Fname,string Sname):Fname(Fname),Sname(Sname){}

	
protected:
	string Fname;
	string Sname;
};
//Subclass
class Son :public Parent
{
public:
	Son() { cout << "Subclass parameterless constructor" << endl; } //Pointer writing, the parent class must have a parameterless constructor, which can also be used by default
	Son(string Fname, string Sname, string sonSname):Parent(Fname,Sname)
	{
		//You can initialize your own properties by any method
		this->sonFname = Fname;
		this->sonSname = sonSname;
	}
	void print()
	{
		cout << "Father:" << Fname + Sname << endl;
		cout << "Son:" << sonFname + sonSname << endl;
	}
protected:
	string sonFname;
	string sonSname;
};

int main()
{
	Son s1;//The subclass constructs the object and calls the parent constructor first
	Son son1("Lee", "dog", "pig");
	son1.print();
	return 0;
}

 

//Multiple inheritance
#include <iostream>
#include <string>
using namespace std;
//Parent class 1
class MM
{
public:
	MM() = default;
	MM(string mmFname, string mmSname)
	{
		this->mmFname = mmFname;
		this->mmSname = mmSname;
	}
protected:
	string mmFname;
	string mmSname;
};
//Parent class 2
class GG
{
public:
	//GG() = default;
	GG(string ggFname, string ggSname)
	{
		this->ggFname = ggFname;
		this->ggSname = ggSname;
	}
protected:
	string ggFname;
	string ggSname;
};
//Subclass
class Girl:public MM,public GG
{
public:
	//Girl() {} / / both parent classes need a parameterless constructor
	//If there is no default constructor, it needs to be initialized with a parameter list. If there is, it does not need to be initialized
	Girl(string mmFname, string mmSname, string ggFname, string ggSname)
		:MM(mmFname,mmSname),GG(ggFname,ggSname)
	{
		girlFname = mmFname + ggFname;
		girlSname = mmSname + ggSname;
	}
	void print()
	{
		cout << "MM name:" << mmFname + mmSname << endl;
		cout << "GG name:" << ggFname + ggSname << endl;
		cout << "Girl name:" << girlFname + girlSname << endl;
	}
protected:
	string girlFname;
	string girlSname;

};
int main()
{
	Girl k("ocean", "son", "Oh", "writing");
	k.print();
	
	return 0;
}

Problems with the same name in inheritance

  • Data member has the same name
  • Member function has the same name

① Subclass objects can directly access members with the same name in subclasses

② The subclass object plus scope can access the member with the same name as the parent class

③ When a subclass has a member function with the same name as the parent class, the subclass will hide the member function with the same name in the parent class, and the scope can access the function with the same name in the parent class

  • The static member processing method is the same as the non static processing method, except that there are two access methods: (through object and through class name)
#include <iostream>
#include <string>
using namespace std;
class MM
{
public:
	MM(string name,int age):name(name),age(age){}
	void print()
	{
		cout << "Parent class printing" << endl;
	}

protected:
	string name;
	int age;
};

class Girl :public MM
{
public:
	Girl(string name,int age):MM("Parent class",88),name(name), age(age) {}
	void print()
	{
		//The principle of proximity without special treatment
		cout << name << " " << age << endl;
		//Qualified by class name, you can print the data of the parent class
		cout << MM::name << " " << MM::age << endl;
		MM::print();//The same is true for functions. It is also the principle of proximity without special treatment, so it is necessary to add class name qualification
	}

protected:
	string name;
	int age;
};

int main()
{
	//Normal object call
	Girl m("Subclass",44);
	m.print();
	MM mm("mm", 11);
	mm.print();

	//Normal pointer call
	//Proximity principle
	Girl* pG = new Girl("newGirl", 23);
	pG->print();
	pG->MM::print();//That's OK
	MM* mG = new MM("newMM", 32);
	mG->print();

	//Abnormal pointer
	//Allow subclass objects to initialize parent class pointers
	MM* pMM = new Girl("newGirl", 999);
	//Is pMM's print MM or Girl?
	//In the absence of virtual, the pointer type and the assignment object will be used
	pMM->print();

	//The parent class object initializes the child class pointer, which is unsafe
	//Girl* pGG = new MM("newMM", 5550);// error
	
	//Trigger interrupt
	//Girl* pgg = (Girl*)mG;
	//pgg->print();
	return 0;
}

diamond inheritance

  • The main problem caused by diamond inheritance is that subclasses inherit two copies of the same data, resulting in waste of resources and meaninglessness
  • Using virtual inheritance can solve the problem of diamond inheritance

#include <iostream>
#include <string>
using namespace std;
class A
{
public:
	A(int a):a(a){}

protected:
	int a;
};
class B :virtual public  A
{
public:
	B(int a,int b):A(a),b(b){}
	void print2()
	{
		cout << a << endl;
	}
protected:
	int b;
};
class C :virtual public  A
{
public:
	C(int a, int c) :A(a),c(c){}
protected:
	int c;
};
class D :public  B,public C
{
public:
	//Diamond inheritance, you must call grandfather's constructor
	D() :B(1, 2), C(3, 4), A(9) {}//It has nothing to do with class B and class C
	void print()
	{
		//There is only one copy, so the printing is the same
		cout << a << endl;
		cout << B::a << endl;
		cout << C::a << endl;
		print2();//The same is true for indirect access
	}
protected:
	
};
int main()
{
	D dd;
	dd.print();
	
	return 0;
}

Topics: C++