继承
一、类的继承方式
1、 定义
在一个已有类的基础上设计新类,从而新类直接获得已有类的所有特性。
已有类称为父类,新生类称为子类或派生类。
2、 语法格式
Class 派生类名:继承方式 基类名1,继承方式 基类2·····
二、继承方式
1、 公有继承public
特点:
在公有继承方式下,基类的公有和保护类成员在派生类中仍然是公有和保护成员,可以由派生类的成员函数访问。派生类的对象可以访问公有的成员,至于基类的私有成员,无论是派生类的成员函数或者派生了的对象都无法访问。
2、 私有继承private
特点:
在私有继承方式下,基类所有的非私有成员在派生类中一律变成派生类的私有成员,派生类只能通过它的成员函数访问,派生类对象不能访问;至于基类的私有成员,只能通过基类的成员函数访问。
3、 保护继承protected
特点:
在保护继承方式下,基类的非私有成员在派生类中变成保护成员,这些成员可以被派生类的成员函数访问,但不能被派生类的对象访问。同样,基类的私有成员仍然在派生类中不可见。
三、派生类的构造函数和析构函数
1、 派生类的构造函数
派生了的数据成员由所有基类的数据成员与派生类新增的数据成员共同组成。
派生类的构造函数必须要以合适的初值作为参数隐含调用基类的构造函数,来初始化基类的数据成员,然后再对新增的数据成员进行初始化。
所有这些参数在派生类的构造函数中都以初始化列表的形式提供,相关语法:
派生类名(参数表):基类名(参数表1),···,基类名(参数表n)
{
派生类新增成员的初始化
}
说明:
(1) 对基类成员和子对象成员的初始化必须在初始化列表中进行,新增成员的初始化既可以在初始化表中进行,也可以在构造函数体中进行。
(2) 派生类构造函数初始化的执行顺序是:先调用基类构造函数初始化基类的数据成员,如果有子对象,随后对子对象进行初始化,最后初始化派生类新增成员。
(3) 当派生类有多个基类时,按声明顺序进行调用。
(4) 如果派生类的基类也是一个派生类,则每个派生类只需负责其直接的构造函数的初始化,依次上溯。
2、 析构函数
析构派生类对象的步骤是:
先调用派生类的析构函数析构派生类对象新增部分,如果该派生类含有子对象,接下来就析构子对象部分,最后调用基类的析构函数析构基类部分。
四、多继承
1、语法:
Class 派生类名:继承方式 基类名1,继承方式 基类2·····
2、多继承的构造函数
按照派生类声明各个基类的先后顺序逐一提供参数并调用相应的构造函数。
3、 多继承引起的二义性
从不同的基类继承的成员同名而产生的二义性。
解决方法:
可以在调用基类同名的成员函数时,加上作用域限定符。
Sb.Sofa::SetWeight(58.2);
Sb.Bed::SetWeight(59.2);
五、虚基类
1、作用:消除多继承产生的二义性。将共同基类设为虚基类,以此保证它的成员在各条派生路径上的唯一性。
2、语法格式:
Class 派生类名:virtual 继承方式基类名
4、 虚基类的初始化
(1) 虚基类的调用顺序在非虚基类之前调用。
(2) 若同一层次中包含多个虚基类,则按他们的声明顺序调用。
(3) 若虚基类由非虚基类派生而来,要先调用更高级别基类的构造函数,再按照(1)和(2)的顺序。
六、组合类
1、 定义
指在一个类的数据成员中包含一个或多个类对象,拥有这样结构的类就叫组合类。
组合类创建的对象和子对象之间是“整体和部分”的关系,也是一种“拥有”关系。
2、 组合类中的构造函数
类名::类名(形参表):基类1(形参表1),···,基类n(形参表n),子对象1(形参表1),···,子对象n(形参表n)
{
本类新增数据成员的初始化;
}
例:设计一个组合类People,包括人员的编号和性别,出生日期(Date类型)。
#include<iostream>
#include<stdlib.h>
using namespace std;
class Date
{
public:
Date();
Date(inty, int m, int d);
voidSetDate(int y, int m, int d);
intIsLeapYear();
voidPrint();
private:
intyear, month, day;
};
class People
{
public:
People(intnum, char s, int n, int m, int d);
~People();
voidSetNum(int n);
voidSetSex(char s);
intGetNum() const;
charGetSex() const;
voidPrint();
private:
intnumber;
charsex;
Datebirthday;
};
………………………………………………………………………..
………………………………………………………………………..
#include"h.h"
Date::Date() //
{
year= 2000;
month= 1;
day= 1;
}
Date::Date(int y, int m, int d)
{
year= y;
month= m;
day= d;
}
void Date::SetDate(int y, int m, int d)
{
year= y;
month= m;
day= d;
}
int Date::IsLeapYear()
{
return(year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}
void Date::Print()
{
cout<< year << "年" << month << "月" << day<< "日" << endl;
}
People::People(int num, char s, int n, intm, int d) :birthday(n, m, d)
{
number= num;
sex= s;
}
People::~People(){}
int People::GetNum() const
{
returnnumber;
}
char People::GetSex() const
{
returnsex;
}
void People::Print()
{
cout<< "编号为" << number << "的人员的出生日期是";
birthday.Print();
}
void People::SetNum(int n)
{
number= n;
}
void People::SetSex(char s)
{
sex= s;
}
………………………………………………………………………..
………………………………………………………………………..
#include"h.h"
int main()
{
Peoplep1(1001, 'F', 2000, 11, 4);
p1.Print();
system("pause");
return0;
}