Summary of knowledge points in Chapter 5 (Inheritance and Derivation) of C++ Object-Oriented Programming (2nd Edition)

C++ object-oriented programming

参考书目:《C++面向对象程序设计》—— 谭浩强 《C++程序设计:思想与方法》—— 翁惠玉



1. The concepts of inheritance and derivation

       Inheritance is a universally important property of nature. Derivation enables new classes to have more colorful personalities while inheriting common features. In object-oriented programming, inheritance is the main means of realizing software reuse in C++. Generally, a hierarchical classification method is used to describe the relationship between things.

Insert image description here

       Summary of class hierarchical relationships:

  • In the class hierarchy diagram, the lower class is a special class of the upper class.

  • The lower class automatically has the characteristics of the upper class, and also has its own new characteristics.

  • The further you go down the hierarchy diagram, the more specific its characteristics become.

  • This top-down hierarchical relationship reflects the process of inheritance and derivation.

  • C++ object-oriented technology also uses this inheritance mechanism.

    注:1.由基类派生出新类的过程称为派生(派生类自身也可以作为基类派生出新的派生类)。
        2.继承是指派生类自动拥有基类的属性和行为特征(派生类自动拥有基类的属性和行为,并表现出自身新的属性和行为特征 )。
    
    类的继承和派生机制使程序员无须修改已有的类,只需在既有类的基础上,根据问题的实际需要,通过增加部分代码或修改少量代码而得到新的类(派生类),从而很好的解决了程序代码的重用问题。
    

       C++ inheritance mechanism:
Insert image description here
       The so-called inheritance is to create a new class B based on the existing class A. Class A is called the base class or parent class, and class B is called the derived class or subclass. A subclass acquires its existing characteristics from its parent class, a phenomenon called class inheritance. From another perspective, generating a subclass from a parent class is called class derivation.

       A base class can derive multiple derived classes, and each derived class can be used as a base class to derive new derived classes. A derived class that only derives from one base class is called single inheritance.
       The specific process is shown in the figure:
Insert image description here

       A derived class can also be derived from multiple base classes, which means a derived class can have two or more base classes. A derived class that has two or more base classes is called multiple inheritance.
       The specific process is shown in the figure:
Insert image description here

2. How to declare derived classes

       The format of derived class declaration: class derived class name: [inheritance method] base class name {new member declaration of derived class};
       inheritance methods include: public, private, protected. If omitted, the system defaults to private.

Example: Assume that a base class student has been declared, and a derived class student1 is created based on it through single inheritance.

class Student
{
    
     
	 private :
	   	int num;
	   	string name;
	   	char sex; 
     public:
	  	void display( )
	  {
    
    	
	      cout<<"num: "<<num<<endl;
	      cout<<"name: "<<name<<endl;
	      cout<<"sex: "<<sex<<endl;
	  }
}; 
class Student1: public Student
{
    
      
     private:
	    int age;
	    string addr;
     public:
	    void display_1()
	  {
    
      
	       cout <<"age: "<<age<<endl;
	       cout <<"address: "<<addr<<endl;
	  }
};

3. Composition of derived classes

       Members in a derived class include members inherited from the base class and members added by oneself. Inherited base class members reflect the common features of derived classes of the same base class, while newly added members reflect the personality of the derived class.
Insert image description here

       Several parts of the work of constructing a derived class:

  1. Receives members from a base class. The derived class receives all the members of the base class except the constructor and destructor. After multiple derivation, there will be a lot of useless data. Therefore, do not randomly find an existing class as a base class to construct a derived class.
  2. Adjust members received from the base class. On the one hand, you can change the access attributes of base class members in derived classes through inheritance. On the other hand, you can declare a member with the same name as the base class member in the derived class to shield the member of the base class with the same name. The meaning of shielding is to replace it with a new member. Old members.
  3. Adding members when declaring a derived class reflects the extension of the functions of the base class by the derived class.
  4. When declaring a derived class, you must also define the constructor and destructor of the derived class yourself.

4. Access attributes of derived class members

       The derived class contains base class members and derived class members, which creates problems with the relationship between these two members and access to attributes. This relationship is determined by a combination of the access attributes of the base class members and the inheritance method of the derived class.

       The general format for deriving a class from a base class:

Insert image description here

1.Public inheritance

       When the inheritance mode of a derived class is public (public) attributes, in the derived class, the access attributes of the public members and protected members of the base class in the derived class do not change, and members of the derived class cannot directly access the private members of the base class.

Insert image description here

class Point	//基类Point类的声明
{
    
    
    public:	//公有函数成员
	   void InitP(float xx = 0, float yy = 0) {
    
     X = xx; Y = yy; }
	   void Move(float xOff, float yOff) {
    
     X += xOff; Y += yOff; }
	   float GetX() {
    
     return X; }
	   float GetY() {
    
     return Y; }
    private:	//私有数据成员
	   float X, Y;
};
class Rectangle : public Point  //派生类声明
{
    
    
    public:	//新增公有函数成员
	   void InitR(float x, float y, float w, float h){
    
    
	    InitP(x, y); //调用基类公有成员函数
		W = w;  H = h;}
	   float GetH() {
    
     return H; }
	   float GetW() {
    
     return W; }
    private:	//新增私有数据成员
	   float W, H;
};
int main()
{
    
    
	Rectangle rect;
	rect.InitR(2, 3, 20, 10);
	//通过派生类对象访问基类公有成员
	rect.Move(3, 2);
	cout << rect.GetX() << ','
		<< rect.GetY() << ','
		<< rect.GetH() << ','
		<< rect.GetW() << endl;
	return 0;
}

Insert image description here

2. Private inheritance

       In a derived class, the public members and protected members of the base class serve as private members of the derived class. Members of the derived class can directly access them, but members of the derived class cannot directly access the private members of the base class. After private inheritance, all base class members become private members or inaccessible members in the derived class and cannot be further derived.

Insert image description here

3. Protect members and protect inheritance

       When the inheritance mode of a derived class is protected inheritance attribute, in the derived class, the public members and protected members of the base class are protected members of the derived class. Members of the derived class can directly access them, but members of the derived class cannot access the base class. Private member of the class. Protected inheritance can derive further, while private inheritance cannot.

Insert image description here
       In conclusion:

  • Regardless of the inheritance method, member functions and friend functions of the derived class can access the public members and protected members of the base class, but cannot access private members.
  • In public inheritance, objects of the derived class can only access public members of the base class.
  • In protected inheritance and private inheritance, objects of the derived class cannot access any members of the base class.
    Insert image description here

4. Access attributes during multi-level derivation

       The multi-level derivation relationship is as shown in the figure: If class A is a base class, class B is a derived class of class A, and class C is a derived class of class B, then class C is also a derived class of class A. Class B is a directly derived class of class A, and class C is an indirectly derived class of class A. Class A is the direct base class of class B and the indirect base class of class C.

Insert image description here

多级派生类的访问属性:
class A //基类
{
    
    
    private:
	   int ka;
    public:
	   int ia;
	protected:
	   void fa( );  
	   int ja;
};
class B: public A       //   public方式
{
    
    
    private:
	   int mb; 
    public:
	   void fb1( );  
	protected:
	   void fb2( );   
};
class C: protected B  //   protected方式
{
    
    
    private:
	   int nc;
	public:
	   void fc1( );  
};

Insert image description here

5. Constructors and destructors of derived classes

1. Simple derived class constructor

       A simple derived class has only one base class and only one level of derivation. The data members of the derived class do not contain objects (i.e. sub-objects) of the base class. When defining the constructor of a derived class, in addition to initializing its own data members, you must also call the constructor of the base class to initialize the data members of the base class.
       The format of the constructor is as follows: derived class name:: derived class name (formal parameters required by the base class, formal parameters required by members of this class): base class name (base class parameter list) {initialization assignment statement for members of this class;} ;
       The base class parameter table lists the actual parameters passed to the base class constructor, which are the parameters in the total parameter table of the derived class constructor. Use the formal parameters of the derived class constructor as the actual parameters of the base class constructor.

Simple derived class constructor

class B
{
    
    
    private:
	   int b;
    public:
	   B();
	   B(int i);
	   void Print() const;
};
class C:public B
{
    
    
    private:
	   int c;
    public:
	   C();
	   C(int i, int j);
	   void Print() const;
};
B::B()
{
    
    
	b = 0; cout << "调用B的默认构造函数." << endl;
}
B::B(int i)
{
    
    
	b = i;  cout << "调用的构造函数." << endl;
}
void B::Print() const
{
    
    
	cout << b << endl;
}
C::C()
{
    
    
	c = 0;
	cout << "调用C的默认构造函数." << endl;
}
C::C(int i, int j) :B(i)
{
    
    
	c = j;
	cout << "调用C的构造函数." << endl;
}
void C::Print() const
{
    
    
	B::Print();   cout << c << endl;
}
void main()
{
    
    
	C obj(5, 6);
	obj.Print();
}

Insert image description here

2. Constructor of a derived class with sub-objects

       In addition to standard types or system-provided types such as string, the data members of a class can also be class types. For example, when declaring a class, it contains data members of the class type: Student s1; the general form of a derived class constructor: derived class name
       :: Derived class name (total parameter list): base class name (actual parameter list), sub-object name (parameter list) {initialization statement for new members of the derived class;}

       The tasks of the derived class constructor include:

  • Initialize base class data members

  • Initialize data members of child objects

  • Initializing data members of derived classes

    注:不能在声明派生类时对子对象初始化,系统在建立派生类对象时调用派生类构造函数对子对象进行初始化。
    

       The order in which derived class constructors are executed is:

  1. Call the base class constructor to initialize the base class data members.

  2. Call the sub-object constructor to initialize the sub-object data members.

  3. Execute the derived class constructor and initialize the derived class data members.

    注:编译系统在此根据参数名(而不是参数的顺序)决定各参数表中参数之间的传递关系。如有多个子对象,要逐个列出子对象及其参数表。
    
#include <iostream>
#include <string>
using namespace std;
class Student                              //声明基类
{
    
    
    public:                                  //公用部分
	   Student(int n, string nam)       //基类构造函数
	   {
    
    num = n;     name = nam;}
	   void display()
	   {
    
    cout << "学号:" << num << endl << "姓名:" << name << endl;}
    protected:                               //保护部分
	   int num;
	   string name;
};
class Student1 : public Student   //   public继承方式
{
    
    
    private:                           //  派生类的私有数据
	   Student monitor;           //  定义子对象(班长)
	   int age;    
	   string addr;
    public:
	   Student1(int n, string nam, int n1, string nam1, int a, string ad) :Student(n, nam), monitor(n1, nam1){
    
    age = a;     addr = ad;}
	   void show()
	   {
    
    
		cout << "这个学生是:" << endl;
		display();            // 输出num和name
		cout << "年龄: " << age << endl;
		cout << "地址: " << addr << endl;
	   }
	   void show_monitor()
	   {
    
    
		cout << endl << "班长是:" << endl;
		monitor.display();  //调用基类成员函数	 
	   }	
};
int main()
{
    
    
		Student1 stud1(101, "王力",110,"李军",19,"上海市北京路115号");
		stud1.show();             //  输出第一个学生的数据
		stud1.show_monitor();     //  输出子对象的数据
		return 0;
}

Insert image description here

3. Constructor in multi-level derivation

       A class can derive a derived class, and derived classes can continue to derive, forming a derived hierarchy.

Insert image description here

可以按照前面派生类构造函数的规则逐层写出各个派生类的构造函数。
基类的构造函数首部:
Student(int n, string nam );
派生类Student1的构造函数首部:
Student1(int n,string nam,int a):Student(n,nam);
派生类Student2的构造函数首部:
Student2(int n,string nam,int a,int s):Student1(n,nam,a);
写派生类构造函数的规则是,只须调用其直接基类的构造函数即可,不要列出每一层派生类的构造函数。
在声明Student2类对象时,调用Student2构造函数,在执行Student2构造函数时,先调用Student1构造函数,在执行Student1构造函数时,先调用基类Student构造函数。
初始化的顺序是:
①先初始化基类的数据成员num和name
②再初始化Student1的数据成员age
③最后初始化Student2的数据成员score
class Student                              //声明基类
{
    
    
    public:
	   Student(int n, string nam)            //基类构造函数
	   {
    
    num = n;     name = nam;}
	   void display()                           //输出基类数据成员
	   {
    
    cout << "num:" << num << endl;   cout << "name:" << name << endl;}
    protected:                                //保护部分
	   int num;        
	   string name;
};
class Student1 : public Student //声明公用派生类Student1
{
    
    
    public:
	   Student1(int n, string nam, int a) :Student(n, nam){
    
    age = a;}     //在此处只对派生类新增的数据成员初始化
	   void show()   //输出num,name和age 
	   {
    
    display(); cout << "age: " << age << endl;}
    private:                                   //派生类的私有数据
	   int age;                                  //增加一个数据成员
};
class Student2 :public Student1   //声明间接公用派生类student2
{
    
    
    public:
	   Student2(int n, string nam, int a, int s) :Student1(n, nam, a)
	   {
    
    score = s;}
	   void show_all()     //  输出全部数据成员
	   {
    
    show();       cout << "score:" << score << endl;}
	private:
	   int score;   //增加一个数据成员
};
int main()
{
    
    
	Student2 stud(10010, "李明", 17, 89);
	stud.show_all();  //输出学生的全部数据
	return 0;
}

Insert image description here

4. Special form of derived class constructor

class A
{
    
    
    public:
	   A() {
    
     a = 0;  cout << "A类无参构造函数被调用" << endl; }
	   A(int i) {
    
     a = i;  cout << "A类有参构造函数被调用" << endl; }
	   void print() {
    
     cout << a << ","; }
	   int b;
    private:
	   int a;
};
class B : public A
{
    
    
    public:
	   B() {
    
     b1 = b2 = 0; }
	   B(int i) {
    
     b1 = 0;  b2 = i; }
	   B(int i, int j, int k) :A(i), b1(j), b2(k) {
    
    	}
	   void print(){
    
    A::print();	cout << b1 << "," << b2 << endl;}
    private:
	   int b1, b2;
};
int main()
{
    
    
	B b1, b2(5), b3(1, 2, 3);    b1.print();	b2.print();  b3.print();
	return 0;
}

Insert image description here

5. Destructor of derived class

       When a class is derived, the derived class cannot inherit the destructor of the base class. When deleting the derived class object, the destructor of the derived class needs to call the destructor of the base class.
       The destructor sequence is as follows: first call the destructor of the derived class -> the destructor of the sub-object -> the destructor of the base class.

class B
{
    
    
    private:	  
       int b;
    public:
	   B() {
    
     b = 0;   cout << "调用B的默认构造函数." << endl; }
	   B(int i) {
    
     b = i;   cout << "调用B的构造函数." << endl; }
	   ~B() {
    
     cout << "调用B的析构函数." << endl; }
	   void Print() const {
    
     cout << b << endl; }
};
class C :public B
{
    
    
    private:  int c;
    public:
	   C() {
    
     c = 0;   cout << "调用C的默认构造函数." << endl; }
	   C(int i, int j) :B(i) {
    
     c = j; cout << "调用C的构造函数." << endl; }
	   ~C() {
    
     cout << "调用C的析构函数." << endl; }
	   void Print() const {
    
     B::Print();	cout << c << endl; }
};
void main() 
{
    
     
    C obj(5, 6);	
    obj.Print(); 
}

Insert image description here

6. Multiple inheritance

       Deriving from only one base class is called single inheritance. When a derived class has two or more base classes at the same time, it is called multiple inheritance.

Insert image description here

1. Declaring multiple inheritance methods

       class Derived class name: inheritance mode 1 base class name 1, inheritance mode 2 base class name 2,...{member declaration;}

注:每一个“继承方式”,只用于限制对紧随其后之基类的继承。若缺省,系统默认为私有继承方式。
class A
{
    
    
    public:
       void setA(int);
       void showA();
    private:
       int a;
};
class B
{
    
    
    public:
       void setB(int);
       void showB();
    private:
       int b;
};
void A::setA(int x) {
    
       a=x;  }
void B::setB(int x) {
    
       b=x;  }
class C : public A, private B
{
    
    
   public:
      void setC(int, int, int);
      void showC();
   private:       
      int c;
}; 
void C::setC(int x, int y, int z)
{
    
       
     setA(x);      setB(y);      c=z;
}  
int main()
{
    
        
     C obj;
     obj.setA(5);   
     obj.showA();
     obj.setC(6,7,9);   
     obj.showC();
     return 0;
}

2. Multiple inheritance of constructors of derived classes

       Constructor form of derived class: derived class constructor name (total parameter list): base class 1 constructor (parameter list), base class 2 constructor (parameter list), base class 3 constructor (parameter list)... { Derived Initialization statement for new member of class }

注:1.各基类的排列顺序不分先后,系统调用基类构造函数的顺序就是声明派生类时基类的出现顺序。2.多继承析构函数的执行顺序与多继承方式下构造函数的执行顺序完全相反,首先对派生类新增的数据成员进行清理,再对派生类对象成员进行清理,最后才对基类继承来的成员进行清理。
class  Base1
{
    
    
	   int  x;
    public:
	   Base1(int a) {
    
     x = a;  cout << "1的构造函数!\n"; }
	   ~Base1() {
    
     cout << "1的析构函数!\n"; }
};
class  Base2 
{
    
    
	   int y;
    public:
	   Base2(int a) {
    
     y = a;  cout << "2的构造函数!\n"; }
	   ~Base2() {
    
     cout << "2的析构函数!\n"; }
};
class Derived :public Base2, public  Base1 
{
    
    
	   int z; 	Base1  b1, b2;
    public:
	   Derived(int a, int b) :
	   Base1(a), Base2(20), b1(200), b2(a + b){
    
    z = b;   cout << "派生类的构造函数!\n";}
	   ~Derived() {
    
     cout << "派生类的析构函数!\n"; }
};
void  main(void)
{
    
    
	Derived   c(100, 200);
}

Insert image description here

3. Ambiguities caused by multiple inheritance

       The most common problem with multiple inheritance is the ambiguity caused by a derived class inheriting a member of the base class with the same name.

注:1.在多重继承时,基类与派生类之间,或基类之间出现同名成员时,将出现访问时的二义性(不确定性)——采用虚函数或同名隐藏规则来解决。2.当派生类从多个基类派生,而这些基类又从同一个基类派生,则在访问此共同基类中的成员时,将产生二义性——采用虚基类来解决。
class B1
{
    
    
    public:
	   int nV;
	   void fun(){
    
    cout << "Member of B1" << endl;}
};
class B2
{
    
    
    public:
	   int nV;
	   void fun(){
    
    cout << "Member of B2" << endl;}
};
class D1 : public B1, public B2
{
    
    
    public:
	   int nV;	//同名数据成员
	   void fun(){
    
    cout << "Member of D1" << endl;}
};
void main()
{
    
    
	D1 d1;
	d1.nV = 1;
	d1.fun();

	d1.B1::nV = 2;
	d1.B1::fun();

	d1.B2::nV = 3;
	d1.B2::fun();
}

Insert image description here
       Same name hiding rule - when there are the same members in the derived class and the base class:

  • If no name is forced, the member with the same name in the derived class will be used through the derived class object.
  • If you want to access an overridden member of the base class with the same name through a derived class object, you should use base class name qualification.

4. Virtual base class

       If a derived class has multiple direct base classes, and these direct base classes have a common base class, multiple members with the same name of this indirect common base class data member will be retained in the derived class. If you do not want to retain multiple members of the indirect common base class with the same name in the derived class, C++ provides a virtual base class method so that the derived class retains only one member when inheriting the indirect common base class.

Insert image description here
       If a constructor with parameters is defined in a virtual base class and no default constructor is defined, the virtual base class is required to be initialized through the initialization table of the constructor in all its derived classes (direct and indirect).

class  A
{
    
     	A (int k) {
    
     } … … 	};
class  B: virtual public A
{
    
    	B (int n ):A(n){
    
     }… … 	};
class  C: virtual public A
{
    
    	C (int n ):A(n){
    
     } … … 	};
class  D: public B,public C
{
    
    	D (int n ):A(n),B(n),C(n) {
    
     } … … 	};
class  A 
{
    
    
    public:	
	   int x;
	   A(int  a = 0) {
    
     x = a; }
};
class B :public  virtual A 
{
    
    
    public:	
	   int y;
	   B(int a = 0, int b = 0) : A(a) {
    
     y = b; }
};
class C :public virtual A 
{
    
    
    public:	
	   int z;
	   C(int a = 0, int c = 0) :A(a) {
    
     z = c; }
};
class D :public B, public C 
{
    
    
    public:	
	   int dx;
	   D(int a1, int b, int c, int d, int a2) :B(a1, b), C(a2, c){
    
    dx = d;}
};
void  main(void)
{
    
    
	D d1(10, 20, 30, 40, 50);
	cout << d1.x << endl;
	d1.x = 400;
	cout << d1.x << endl;
	cout << d1.y << endl;
}

Insert image description here
       The rules for calling order of virtual base class constructors:

  • If the same hierarchy contains only multiple virtual base classes, call them in the order in which they are declared, and then call the constructor of the derived class.
  • If the virtual base class is derived from a non-virtual base class, the non-virtual base class constructor is called first, and then the derived class constructor is called.
  • If the same level contains both virtual base classes and non-virtual base classes, the constructor of the virtual base class is called first, then the constructor of the non-virtual base class is called, and finally the derived class constructor is called.

       The rules for calling order of multiple inheritance constructors:

  1. Call the constructor of the virtual base class in the order in which the virtual base class is inherited;
  2. Call the constructors of non-virtual base classes in the order in which they are inherited from non-virtual base classes;
  3. Call the constructors of member objects in the order in which they are declared;
  4. Call the derived class's own constructor.
class OBJ1
{
    
    
    public:   OBJ1() {
    
     cout << "调用OBJ1类构造函数" << endl; }
};
class OBJ2
{
    
    
    public:   OBJ2() {
    
     cout << "调用OBJ2类构造函数" << endl; }
};
class Base1
{
    
    
    public:   Base1() {
    
     cout << "调用Base1类构造函数" << endl; }
};
class Base2
{
    
    
    public:   Base2() {
    
     cout << "调用Base2类构造函数" << endl; }
};
class Base3
{
    
    
    public:   Base3() {
    
     cout << "调用Base3类构造函数" << endl; }
};
class Base4
{
    
    
    public:   Base4() {
    
     cout << "调用Base4类构造函数" << endl; }
};
class Derived :public Base1, virtual public Base2,public Base3, virtual public Base4
{
    
    
    public:
	   Derived() :Base4(), Base3(), Base2(), Base1(), obj1(), obj2(){
    
    cout << "调用派生类构造函数成功!" << endl;}
    protected:	
	   OBJ1 obj1;	
	   OBJ2 obj2;
};
int main()
{
    
    
	Derived aa;
	cout << "派生类对象 aa 构造成功,谢谢!" << endl;
	return 0;
}

Insert image description here

7. Type Compatibility Rules

1. Assignment compatibility rules

       An object of a public derived class can be used as an object of the base class, but vice versa is prohibited, which is called assignment compatibility rule.

       Specifically in:

  • Objects of derived classes can be assigned to base class objects.
  • Objects of derived classes can assign or initialize references to base class objects.
  • Function parameters are base class objects or references thereof, and corresponding actual parameters can use derived class objects.
  • A pointer to a base class object can also point to a derived class object.
  • Only members inherited from the base class can be used through base class object names and pointers.
如(1):
A a1; // 定义基类 A 对象 a1 
B b1; // 定义类 A 的公用派生类 B 的对象 b1 
a1=b1; // 用派生类 B 对象 b1 对基类对象 a1 赋值,在赋值时舍弃派生类自己的成员 。 
注:赋值后不能企图通过对象 a1 去访问派生类对象 b1 的成员,因为 b1 的成员与 a1 的成员是不同的。

       Assignment compatibility rules:

  • You can only use subclass objects to assign values ​​to their base class objects, but you cannot use base class objects to assign values ​​to their subclass objects.
  • Values ​​cannot be assigned between objects of different derived classes of the same base class.
如(2):
A a1; // 定义基类 A 对象 a1 
B b1; // 定义公用派生类 B 对象 b1 
A&r=a1; // 定义基类 A 对象的引用,并用 a1 初始化。
注:1.可以用子类对象初始化引用变量 r,将最后一行改为: A& r=b1;2.保留上面第 3 行 “A& r=a1;” ,而对 r 重新赋值: r=b1;
如(3):
函数fun: 
void fun(A& r)    // 形参是类 A 的对象的引用 
{
    
    cout<<r.num<<endl; }
由于子类对象与派生类对象赋值兼容,派生类对象能自动转换类型,在调用 fun 函数时可以用派生类 B 的对象 b1 作实参 : 
fun(b1); 输出类 B 的对象 b1 的基类数据成员 num 的值。
如(4):指向基类对象的指针,也可以指向派生类对象。
class Student
{
    
    
    public:
	   Student(int, string, float);
	   void display();
    private:
	   int num;
	   string name;
	   float score;
};
Student::Student(int n, string nam, float s)
{
    
    num = n;    name = nam;    score = s;}
void Student::display()
{
    
    cout << endl << "num:" << num << endl << "name:" << name << endl << "score:" << score << endl;}
class Graduate :public Student
{
    
    
    public:
	   Graduate(int, string, float, float);
	   void display();
    private:
	   float pay;// 工资 
};
Graduate::Graduate(int n, string nam, float s, float p) : Student(n, nam, s), pay(p) {
    
     }
void Graduate::display() {
    
     Student::display(); cout << "pay = "<< pay << endl; }
void main()
{
    
    
	Student stud1(1001, "Li", 87.5);
	Graduate grad1(2001, "Wang", 98.5, 563.5);
	Student *pt = &stud1;
	pt->display(); // 调用 stud1.display 函数
	pt = &grad1; // 指针指向 grad1
	pt->display(); // 调用 grad1.display 函数 
}

Insert image description here

2. Inheritance and combination

       Using objects of another class as data members in one class is called class composition. Class composition, like inheritance, is an important way of software reuse. Establishing a "yes" relationship between a derived class and a base class through inheritance. There is a "there" relationship between member classes and composite classes established through combination. Inheritance is vertical, composition is horizontal.

class Teacher// 教师类 
{
    
        
     public:private:	
	    int num; 	
	    string name; 	
	    char sex; 
}; 
class BirthDate
{
    
     
     public:
     private: 	
        int year; 	
        int month; 		
        int day; 
};
class Professor: public Teacher
{
    
        
     public:private:    
        BirthDate birthday;
}; 	
Professor 类通过继承,从 Teacher 类得到了 num, name,age,sex 等数据成员。
通过组合,从 BirthDate 类得到了 year,month,day 等数据成员 。

Guess you like

Origin blog.csdn.net/weixin_43312470/article/details/108045954