一、多级派生时的访问属性
C-->B-->A
类B称为类A的直接派生类,类C称为类A的间接派生类。类A是类B的直接基类,类A是类C的间接基类。
例:多级派生的访问属性
#include <iostream>
using namespace std;
class A
{
public:
int i;
protected:
void f1();
int j;
private:
int k;
};
class B:public A//public派生类
{
public:
void f2();
protected:
void f3();
private:
int m;
};
class C:protected B//protected派生类
{
public:
void f4();
private:
int n;
};
对于上面的这个代码来看,可以得到下表的关系:
类别 | i | f1() | j | k | f2() | f3() | m | f4() | n |
基类A | 公用 | 被保护的 | 被保护的 | 私有的 | |||||
基类B | 公用 | 被保护的 | 被保护的 | 不可访问 | 公用 | 被保护的 | 私有的 | ||
基类C | 被保护的 | 被保护的 | 被保护的 | 不可访问 | 被保护的 | 被保护的的 | 不可访问 | 公用 | 私有的 |
二、派生类的构造函数和析构函数
构造函数:
主要作用是对数据成员初始化。
在声明派生类时,派生类并没有把基类的构造函数继承过来,因此对继承过来的基类成员初始化的工作要由派生类的构造函数函数承担。
希望达成的目标是:
在执行派生类的构造函数时,使派生类的数据成员和基类的数据成员同时都被初始化。
解决思路:
在执行派生类的构造函数时,调用基类的构造函数。
a、简单的派生类的构造函数
例:定义简单的派生类的构造函数
#include <iostream>
#include <string>
using namespace std;
class Student
{
public:
Student(int n, string nam, char s)//定义构造函数
{
num = n;
name = nam;
sex = s;
}
~Student() {}
protected:
int num;
string name;
char sex;
};
class Student1 :public Student
{
public:
Student1(int n, string nam, char s, int a, string ad):Student(n, nam, s)//定义派生类构造函数
{
age = a;
address = ad;
}
void show()
{
cout << "num=" << num << endl;
cout << "name=" << name << endl;
cout << "sex=" << sex << endl;
cout << "age=" << age << endl;
cout << "address=" << address << endl;
}
~Student1() {}
private:
int age;
string address;
};
int main()
{
Student1 sutd1(10010, "Wang-li", 'f', 19, "115 beijing road,shanghai");
Student1 stud2(10011, "zhang-fan", 'm', 21, "213 shanghai road,beijing");
sutd1.show();
stud2.show();
return 0;
}
运行结果:
派生类构造函数一般形式为:
派生类构造函数名(总参数表):基类构造函数名(参数表)
{
派生类中新增数据成员初始化语句
}
注:这里不是定义基类构造函数,而是调用基类构造函数,因此这些参数是实参而不是形参。
b、有子对象的派生类构造函数
Student s1;//Student是已声明的类名,s1是Student类的对象
子对象的定义:
这时s1就是类对象中的内嵌对象,称为子对象,即对象中的对象。
例:包含子对象的派生类的构造函数
#include<iostream>
#include<string>
using namespace std;
class Student
{
public:
Student(int n, string nam)
{
num = n;
name = nam;
}
void display()
{
cout << "num=" << num << endl;
cout << "name=" << name << endl;
}
~Student(){}
protected:
int num;
string name;
};
class Student1 :public Student
{
public:
Student1(int n, string nam, int n1, string nam1, int a, string ad) :Student(n, nam),monitor(n1,nam1)//monitor(班长)
{
age = a;
addr = ad;
}
void show()
{
cout << "This student is:" << endl;
display();
cout << "age:" << age << endl;
cout << "address:" << addr << endl;
}
void show_monitor()//成员函数输出子对象班长
{
cout << endl << "class monitor is:" << endl;
monitor.display();
}
~Student1(){}
private:
Student monitor;//定义子对象班长
int age;
string addr;
};
int main()
{
Student1 stud1(10010, "wang_li", 10001, "li_jun", 19, "115 beijing road,shanghai");
stud1.show();
stud1.show_monitor();
return 0;
}
运行结果:
派生类构造函数的任务包括3个部分:
1、对基类数据成员的初始化
2、对子类数据成员的初始化
3、对派生类数据成员初始化
调用派生类构造函数的顺序是:
1、调用基类构造函数,对基类数据成员初始化2、调用子对象构造函数,对子对象数据成员初始化
3、执行派生类构造函数本身,对派生类数据成员初始化