基类与派生类对象的关系 派生类的构造函数

简介: 🐰 基类与派生类对象的关系 🐰派生类的构造函数

🚀🚀🚀大家觉不错的话,就恳求大家点点关注,点点小爱心,指点指点🚀🚀🚀

目录

🐰 基类与派生类对象的关系

🐰派生类的构造函数


🐰 基类与派生类对象的关系

前提引入:

公用派生类具有基类的全部功能(可以通过基类的公用成员函数访问基类的私有成员),所有基类能够实现的功能,公用派生类都能实现。而非公用派生类(私有或保护派生类)不能实现基类的全部功能。因此,基类对象与公用派生类对象之间有赋值兼容关系。

(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;

注意:在赋值时时舍弃派生类新增成员,所谓的赋值只对数据成员赋值,对成员函数不存在赋值

3A4C7C9D-6EBD-4DC0-9F97-236CE91F82E8.jpeg

注意:基类对象是不能对公用派生类进行赋值,例如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赋值

22A9EE3D-243B-4829-B6C0-AF7EF7486D5F.jpeg

同样,公用派生类对象的地址可以代替基类对象地址向指向基类对象的指针进行赋值或初始化,即指向基类对象的指针也可以指向公用派生类对象。但是通过指向基类对象的指针只能访问公用派生类对象中基类成员,而不能访问公用派生类对象新增的成员。

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)如果基类中没有定义构造函数,或者定义了没有构造参数的构造函数那么在定义派生类构造函数时,在其初始化列表中可以不写对基类构造函数的调用。在调用派生类构造函数时,系统会自动调用基类的默认构造函数。

如果基类中定义了无参构造函数,又定义了有参的构造函数(构造函数的重载),则在定义派生类构造函数时,在其初始化列表中既可以包含对基类构造函数的调用,也可以不用,根据创建派生类的需求来采用哪种方式。

🌸🌸🌸如果大家还有不懂或者建议都可以发在评论区,我们共同探讨,共同学习,共同进步。谢谢大家! 🌸🌸🌸



相关文章
|
4月前
|
编译器 C++
51基类与派生类的转换
51基类与派生类的转换
28 0
|
4月前
|
设计模式 Java 编译器
面向对象编程中的继承与多态:深入理解父类引用指向子类实例
面向对象编程中的继承与多态:深入理解父类引用指向子类实例
|
安全 Java 编译器
C++将派生类赋值给基类
在 C/C++ 中经常会发生数据类型的转换,例如将 int 类型的数据赋值给 float 类型的变量时,编译器会先把 int 类型的数据转换为 float 类型再赋值;反过来,float 类型的数据在经过类型转换后也可以赋值给 int 类型的变量。 数据类型转换的前提是,编译器知道如何对数据进行取舍。例如: int a = 10.9; printf("%d\n", a); 输出结果为 10,编译器会将小数部分直接丢掉(不是四舍五入)。再如: float b = 10; printf("%f\n", b); 输出结果为 10.000000,编译器会自动添
126 0
|
1月前
|
编译器 C++
C++的基类和派生类构造函数
基类的成员函数可以被继承,可以通过派生类的对象访问,但这仅仅指的是普通的成员函数,类的构造函数不能被继承。构造函数不能被继承是有道理的,因为即使继承了,它的名字和派生类的名字也不一样,不能成为派生类的构造函数,当然更不能成为普通的成员函数。 在设计派生类时,对继承过来的成员变量的初始化工作也要由派生类的构造函数完成,但是大部分基类都有 private 属性的成员变量,它们在派生类中无法访问,更不能使用派生类的构造函数来初始化。 这种矛盾在C++继承中是普遍存在的,解决这个问题的思路是:在派生类的构造函数中调用基类的构造函数。 下面的例子展示了如何在派生类的构造函数中调用基类的构造函数:
23 1
|
3月前
|
数据安全/隐私保护
继承——基类与派生类
继承——基类与派生类
|
4月前
|
编译器 C++
C++程序中的派生类构造函数
C++程序中的派生类构造函数
40 1
|
4月前
|
安全 程序员 编译器
C++程序中的基类与派生类转换
C++程序中的基类与派生类转换
29 1
<c++> 类的继承 | 基类与派生类 | 构造函数与析构函数
<c++> 类的继承 | 基类与派生类 | 构造函数与析构函数
127 0
基于C/C++将派生类赋值给基类的详细讲解
基于C/C++将派生类赋值给基类的详细讲解
179 0
关于纯虚函数继承子类 ,父类指向子类后 将父类指针转为子指针,就可以调用子类其他接口
关于纯虚函数继承子类 ,父类指向子类后 将父类指针转为子指针,就可以调用子类其他接口
关于纯虚函数继承子类 ,父类指向子类后 将父类指针转为子指针,就可以调用子类其他接口