文章目录
C++程序笔记——继承和多态程序实例
派生类构造函数和析构函数程序实例
知识点
-
构造函数和析构函数调用顺序
- 当创建派生类对象时,先调用基类的构造函数,在调用派生类的构造函数
- 析构函数的调用顺序总是和构造函数的调用顺序相反
-
派生类构造函数的声明方法
<派生类类名>(形参列表):<基类类名>(基类初始化的形参列表)
C++实现代码
person.h文件
#include <iostream>
#include <string.h>
using namespace std;
#ifndef _PERSON_H_
#define _PERSON_H_
class Person
{
private:
char m_name[20];
bool m_sex;
//true representing male, false representing female
public:
Person(char *name,bool sex)
{
strcpy(m_name,name);
m_sex = sex;
cout<<"Person is constructing"<<endl;
}
~Person(){
cout<<"Person is deleting"<<endl;}
};
#endif // _PERSON_H_
Student.h文件
#include "Person.h"
#include <iostream>
#include <string.h>
using namespace std;
class Student1:public Person
{
private:
char m_sno[8];
char m_major[20];
public:
Student1(char *sno,char *major,char *name,bool sex):Person(name,sex)
{
strcpy(m_sno,sno);
strcpy(m_major,major);
cout<<"the object of student is constructing"<<endl;
}
~Student1()
{
cout<<"Student is deleting"<<endl;
}
};
测试的main函数
#include <iostream>
#include "Student1.h"
#include "Person.h"
using namespace std;
int main()
{
Student1 stu("16082022","computer science and technology","gray",true);
return 0;
}
效果图
函数重定义和派生类的继承方式的实例
知识点
- 关于方法重定义,父类和子类的方法名称,返回类型,和参数列表要完全相同
编写运行的样例
-
父类的方法
-
子类重定义后
-
测试函数
- 实验结果
分析与总结
- 父类调用重定义后的方法,是父类的原来的方法,子类调用,就是子类重定义之后的方法
- 主要是公有继承,都能访问父类的私有成员和方法,其余都可。
多重继承下的派生类定义
知识点
- 使用方法
- 在创建通过多重继承定义的派生类对象时,会先调用基类的构造函数,在调用派生类的构造函数,调用顺序和多重继承的顺序一致
- 析构函数的调用顺序总是与构造函数的调用顺序相反
C++代码实现
类体说明
代码
- Person.h文件
#include <iostream>
#include <string.h>
using namespace std;
#ifndef _PERSON_H_
#define _PERSON_H_
class Person
{
private:
char m_name[20];
bool m_sex;
//true representing male, false representing female
public:
Person(char *name,bool sex)
{
strcpy(m_name,name);
m_sex = sex;
cout<<"Person is constructing"<<endl<<endl;
}
~Person(){
cout<<"Person is deleting"<<endl;}
char *getName(){
return m_name;}
bool getSex(){
return m_sex;}
void SetName(char *name){
strcpy(m_name,name);}
void displayInfo()
{
cout<<"the function of father"<<endl;
cout<<"name:"<<m_name<<endl;
cout<<"sex:"<<m_sex<<endl;
cout<<endl;
}
};
#endif // _PERSON_H_
- Student1.h文件
#include "Person.h"
#include <iostream>
#include <string.h>
using namespace std;
class Student1:public Person
{
private:
char m_sno[8];
char m_major[20];
public:
Student1(char *sno,char *major,char *name,bool sex):Person(name,sex)
{
strcpy(m_sno,sno);
strcpy(m_major,major);
cout<<"the object of student is constructing"<<endl<<endl;
}
~Student1()
{
cout<<"Student is deleting"<<endl;
}
void setSNO(char *sno){
strcpy(m_sno,sno);}
char *getSNO(){
return m_sno;}
void setMajor(char *major){
strcpy(m_major,major);}
char *getMajor(){
return m_major;}
void displayInfo()
{
cout<<"the function of children"<<endl;
cout<<"name:"<<getName()<<endl;
cout<<"sex:"<<getSex()<<endl;
cout<<"no:"<<m_sno<<endl;
cout<<"major:"<<m_major<<endl;
cout<<endl;
}
};
- Teacher.h文件
#include "Person.h"
#include <iostream>
using namespace std;
class Teacher:public Person
{
private:
char m_tno[6];
char m_depart[20];
public:
Teacher(char *name,bool sex,char *tno,char *depart):Person(name,sex)
{
strcpy(m_tno,tno);
strcpy(m_depart,depart);
cout<<"the constructor is being used!!"<<endl;
}
~Teacher(){
cout<<"the destructor of teacher is being used!!"<<endl;}
void setTno(char *tno){
strcpy(m_tno,tno);}
char *getTno(){
return m_tno;}
void setDepart(char *depart){
strcpy(m_depart,depart);}
char *getDepart(){
return m_depart;}
};
- TA.h文件
#include "Student1.h"
#include "Teacher.h"
#include <iostream>
using namespace std;
class TA:public Student1,public Teacher
{
public:
TA(char *tno,char *name,char *sno,char *major,char *depart,bool sex)
:Teacher(name,sex,tno,depart),Student1(sno,major,name,sex)
{
cout<<"the constructor of TA is being used!!"<<endl;
}
~TA(){
cout<<"the destructor of TA is being used!!"<<endl;}
};
- 测试文件
#include <iostream>
#include "TA.h"
using namespace std;
int main()
{
TA ta("1210102","gray","11111111","computer science and technology"
,"software programming",true);
return 0;
}
分析与总结
- 不得不说,C++的派生类的声明和初始化着实很费劲,还要和父类初始化的参数列表顺序一致,而且相同参数要写两遍,致使一行句子可以写的长出天际
- 不要重复引入文件,只需要引入最底下的派生类即可,因为在其基类的文件中已经引入了对应的基类所在的文件
多重继承中的二义性问题
- TA分别继承了Teacher类和Student类,而二者又各自继承了Person类,如果通过TA调用Person类就会发生编译错误,因为系统不知道调用哪个类的Person类成员
解决办法
- 指定特定的父类都调用父类的父类,减少二义性的出现
- 使用虚拟继承和虚拟基类
使用虚拟继承和虚拟基类
针对问题
解决类的多重继承中的二义性
声明方式
定义
初始化