🚀🚀🚀大家觉不错的话,就恳求大家点点关注,点点小爱心,指点指点🚀🚀🚀
目录
🐰 基类与派生类对象的关系
前提引入:
公用派生类具有基类的全部功能(可以通过基类的公用成员函数访问基类的私有成员),所有基类能够实现的功能,公用派生类都能实现。而非公用派生类(私有或保护派生类)不能实现基类的全部功能。因此,基类对象与公用派生类对象之间有赋值兼容关系。
(1)公用派生类对象可以向基类对象赋值
由于公用派生类具有基类所有成员,所以把公用派生类的对象赋给基类对象
1. Person person("Marry","F",19);//定义基类Person对象person 2. //定义基类Person的公用派生类Student的对象student 3. Student student("Marry","F",19,"214210203","2021.9.1",680); 4. person=student;
注意:在赋值时时舍弃派生类新增成员,所谓的赋值只对数据成员赋值,对成员函数不存在赋值
注意:基类对象是不能对公用派生类进行赋值,例如student=person是不存在的。因为基类成员中不包含派生类的新增成员,无法对派生类新增成员赋值,同一基类的不同派生类的对象之间也不能进行赋值。
(2)公用派生类对象可以代替基类对象向基类对象的引用进行赋值或初始化
1. Person person("Marry","F",19); 2. Student student("Marry","F",19,"214210203","2021.9.1",680); 3. //定义基类Person的对象引用personref,并用person对其初始化 4. Person &personref=person; 5. //也可以用对象student对引用personref进行初始化,将上面的语句Person &personref=person;修改为 6. Person &personref=student; 7. //或者 8. Person &personref=person; 9. personref=student;//用派生类对象student对person的引用personref赋值
同样,公用派生类对象的地址可以代替基类对象地址向指向基类对象的指针进行赋值或初始化,即指向基类对象的指针也可以指向公用派生类对象。但是通过指向基类对象的指针只能访问公用派生类对象中基类成员,而不能访问公用派生类对象新增的成员。
(3)如果函数参数是基类对象或基类对象的引用,相应的实参可以使用公用派生类对象。
例如:
1. void show(Person &ref) 2. { 3. cout<<ref.show()<<endl; 4. } 5. 则调用函数show时可以使用基类Person的公用派生类对象作为实参: 6. //定义基类Person的公用派生类Student的对象student 7. Student student("Marry","F",19,"214210203","2021.9.1",680); 8. show(student);
同样,如果函数的参数是指向基类的对象的指针,相应的实参可以为公用派生类的对象的地址。
1. void show(Person *p) 2. { 3. Cout<<p->show()<<endl; 4. } 5. 则在调用函数show时可以使用student的地址作为实参: 6. Show(&student);
🐰派生类的构造函数
派生类的构造函数
构造函数的作用是创建对象时对对象的数据成员进行初始化。派生类数据成员包括从基类继承过来的数据成员和自己新增加的数据成员,但是派生类并不能直接初始化从基类继承过来的数据成员,他必须使用基类的构造函数来初始化它们,在派生类构造函数的初始化列表中写出对基类构造函数的调用。
派生类的构造函数:
1. #include<iostream> 2. using namespace std; 3. class Person 4. { 5. public: 6. Person()//无参的默认构造函数 7. { 8. ; 9. } 10. Person(string Name,string Sex,int Age):name(Name),sex(Sex),age(Age)//有参的构造函数 11. { 12. cout<<"The constructor of base class Person is called. "<<endl; 13. } 14. void show() 15. { 16. cout<<"The person's name:"<<name<<endl; 17. cout<<" sex:"<<sex<<endl; 18. cout<<" age:"<<age<<endl; 19. } 20. ~Person()//默认的析构函数 21. { 22. ; 23. } 24. protected: 25. string name; 26. string sex; 27. int age=0; 28. }; 29. class Student:public Person//声明基类Person的公用派生类Student 30. { 31. public: 32. Student()//无参的默认构造函数 33. { 34. ; 35. } 36. Student(string Name,string Sex,int Age,string Id,string Date,floatScore):Person(Name,Sex,Age),id(Id),date(Date),score(Score)//有参的构造函数,在初始化列表中调用基类的构造函数 37. { 38. cout<<"The constructor of base class Student is called. "<<endl; 39. } 40. void stushow() 41. { 42. cout<<" student's id:"<<id<<endl; 43. cout<<" name:"<<name<<endl; 44. cout<<" sex:"<<sex<<endl; 45. cout<<" age:"<<age<<endl; 46. cout<<" date:"<<date<<endl; 47. cout<<" score:"<<score<<endl; 48. } 49. ~Student() 50. { 51. ; 52. } 53. protected: 54. string id; 55. string date; 56. float score=0.0; 57. }; 58. int main() 59. { 60. Student stu("Marry","man",19,"214210203","2021.09.01",523); 61. stu.show(); 62. stu.stushow(); 63. return 0; 64. } 65. 运行结果: 66. The constructor of base class Person is called. 67. The constructor of base class Student is called. 68. The person's name:Marry 69. sex:man 70. age:19 71. student's id:214210203 72. name:Marry 73. sex:man 74. age:19 75. date:2021.09.01 76. score:523
Student(string Name,string Sex,int Age,string Id,string Date,floatScore):Person(Name,Sex,Age),id(Id),date(Date),score(Score)//有参的构造函数,在初始化列表中调用基类的构造函数
冒号前面是派生类Student构造函数的主干,它和以前的构造函数形式相同,但是它的总参数列表中包含着调用基类Person的构造函数所需的参数和对派生类新增的数据成员初始化所需的参数。通过冒号后面的初始化列表完成将参数传递给基类的构造函数和对派生类新增数据成员的初始化工作。
派生类构造函数的具体执行过程:
先调用基类的构造函数,对派生类对象从基类继承过来的数据成员(name,sex,age)进行初始化。接下来初始化派生类新增的数据成员(id,date,score)。最后执行派生类构造函数的函数体。
定义派生类的构造函数,以下几种情况需要注意:
(1)多级派生类的构造函数。一个类不仅可以派生出一个类,派生类还可以继续派生,形成派生的层次结构。在派生层次结构中,每一层派生类的构造函数只负责调用其上一层(即它的直接基类)的构造函数。例如,在派生类Student再派生出派生类Graduate,则派生类Gradute的构造函数如下:
1. class Gradute:public Student 2. { 3. public: 4. Gradute() 5. { 6. ; 7. } 8. Gradute(string Name,string Sex,int Age,string Id,string Date,float Score,stringDirect,string Teacher):Student(Name,Sex,Age,Id,Date,Score),direct(Direct),teacher(Teacher) 9. { 10. cout<<"The constructor of base class Gradute is called. "<<endl; 11. } 12. void gradShow() 13. { 14. cout<<" student's id:"<<id<<endl; 15. cout<<" name:"<<name<<endl; 16. cout<<" sex:"<<sex<<endl; 17. cout<<" age:"<<age<<endl; 18. cout<<" date:"<<date<<endl; 19. cout<<" score:"<<score<<endl; 20. cout<<" direct:"<<direct<<endl; 21. cout<<" teacher:"<<teacher<<endl; 22. } 23. protected: 24. string direct; 25. string teacher; 26. };
(2)当不需要对派生类新增的成员进行任何初始化操作时,此派生类构造函数的作用只是为了将参数传递给基类构造函数。
(3)如果基类中没有定义构造函数,或者定义了没有构造参数的构造函数那么在定义派生类构造函数时,在其初始化列表中可以不写对基类构造函数的调用。在调用派生类构造函数时,系统会自动调用基类的默认构造函数。
如果基类中定义了无参构造函数,又定义了有参的构造函数(构造函数的重载),则在定义派生类构造函数时,在其初始化列表中既可以包含对基类构造函数的调用,也可以不用,根据创建派生类的需求来采用哪种方式。
🌸🌸🌸如果大家还有不懂或者建议都可以发在评论区,我们共同探讨,共同学习,共同进步。谢谢大家! 🌸🌸🌸