为什么要使用继承:
•最高层(基类):是最普遍、最一般的
•低层(派生类):比它的上一层更具体,并且含有高层的特性(继承),同时也与高层有细微的不同
•继承性是程序设计中一个非常有用的、有力的特性,它可以让程序员在既有类的基础上,通过增加少量代码或修改少量代码的方法得到新的类,从而较好地解决了代码重用的问题
一般格式:
class 派生类名:派生方式基类名{
//派生类新增的数据成员和成员函数
};
派生分类:
?在声明派生类时,根据“派生方式”所写的关键字不同可以分为三种派生方式:?用public关键字的为公有派生方式?用private关键字的为私有派生方式?用protected关键字的为保护派生方式
?从继承源上分:?单继承:指每个派生类只直接继承了一个基类的特征?多继承:指多个基类派生出一个派生类的继承关系,多继承的派生类直接继承了不止一个基类的特征
class employee:publicperson{
//…
};
•基类中的私有成员–>派生类中不可访问
•基类中的公有成员–>派生类中是公有的
//公有派生
#include <iostream>
using std::cin;
using std::cout;
using std::endl;
class Base{ //基类
private:
int x;
public:
int y;
void setXY(int n,int m){
x = n;
y = m;
}
void showXY(){
cout<<x<<','<<y<<endl;
}
};
class Derived:public Base{ //公有派生类
private:
int z;
public:
void setZ(int m){
z = m;
}
/*void show(){
cout<<x<<','<<y<<','<<z<<endl;
}*/
};
int main()
{
Derived obj;
obj.y = 3;
obj.setXY(10,20); //ok
obj.setZ(30); //ok
obj.showXY(); //ok
//obj.show(); //okx
return 0;
}
?私有派生
class employee:privateperson{
//…
};
•基类中的私有成员–>派生类中不能访问
•基类中的公有成员–>派生类中是私有的
//私有继承
#include <iostream>
using std::cin;
using std::cout;
using std::endl;
class base{ //基类
private:
int x;
int y;
public:
void setXY(int n,int m){
x = n;
y = m;
}
void showXY(){
cout<<x<<','<<y<<endl;
}
};
class derived:private base{ //私有派生类
private:
int z;
public:
void set(int n,int m,int r){
setXY(n,m);
z = r;
}
void show(){
cout<<z<<endl;
showXY();
//cout<<x<<','<<y<<','<<z<<endl; //?
}
};
int main()
{
derived obj;
// obj.setXY(10,20); //?
obj.set(10,20,30);
obj.show();
return 0;
}
?私有成员在派生类中是无权直接访问的,只能通过调用基类中的公有成员函数的方式实现
?一定要直接访问基类中的私有成员,可以把这些成员声明为保护成员rotected。一般格式:
class 类名{
private:
私有成员
protected:
保护成员
public:
公有成员
};
//不涉及派生时,保护成员与私有成员的地位完全一致。
#include <iostream>
using std::cin;
using std::cout;
using std::endl;
class Samp{
private:
int a;
protected:
int b;
public:
int c;
Samp(int n,int m){
a = n;
b = m;
}
int getA(){
return a;
}
int getB(){
return b;
}
};
int main()
{
Samp obj(20,30);
//obj.a = 11; //Error,私有成员
//obj.b = 22; //Error,保护成员
obj.c = 33; //Ok
cout<<obj.getA()<<' '<<obj.getB()<<endl; //Ok
return 0;
}
//基类中的保护成员在公有派生的派生类中仍是保护的
#include <iostream>
using std::cin;
using std::cout;
using std::endl;
class Base{
protected:
int a, b;
public:
void setAB(int n,int m){
a = n;
b = m;
}
};
class Derive:public Base{
private:
int c;
public:
void setC(int n){
c = n;
}
void showABC(){
cout<<a<<' '<<b<<' '<<c<<endl;
}
};
int main()
{
Derive obj;
//obj.a = 3;
obj.setAB(2,4);
obj.setC(3);
obj.showABC();
return 0;
}
//构造函数与析构函数的执行顺序
#include <iostream>
using std::cin;
using std::cout;
using std::endl;
class Base{
protected:
int a;
public:
void setA(int sa){
a = sa;
}
};
class Derive1:private Base{
protected:
int b;
public:
void setB(int sb){
b = sb;
}
};
class Derive2:public Derive1{
private:
int c;
public:
void setC(int sc){
c = sc;
}
void show(){
cout<<a<<' '<<b<<' '<<c<<endl;
//cout<<b<<' '<<c<<endl;
}
};
int main()
{
Base op1;
op1.setA(1);
Derive1 op2;
op2.setB(2);
Derive2 op3;
op3.setC(3);
op3.setB(4);
op3.show();
return 0;
}
•基类中的私有成员–>派生类中不能访问
•基类中的公有成员–>派生类中是保护的保护派生
class employee:protectedperson{
//…
};
//保护派生
#include <iostream>
using std::cin;
using std::cout;
using std::endl;
class Base{ //基类
private:
int x;
public:
int y;
void setXY(int n,int m){
x = n;
y = m;
}
void showXY(){
cout<<x<<','<<y<<endl;
}
};
class Derived:protected Base{ //保护派生类
private:
int z;
public:
void setXYZ(int a,int b,int m){
setXY(a,b);
z = m;
}
void show(){
showXY();
cout<<z<<endl;
}
};
int main()
{
Derived obj;
//obj.y = 3; //error
//obj.setXY(10,20); //error
obj.setXYZ(10,20,30); //ok
// obj.showXY(); //error
obj.show(); //okx
return 0;
}
��多继承可以看作是单继承的扩展。所谓多继承是指派生类具有多个基类,派生类与每个基类之间的关系仍可看作是一个单继承。
��多继承下派生类的定义格式如下:
class <派生类名>:<继承方式1><基类名1>,<继承方式2><基类名2>,…{
<派生类类体>
};
其中,<继承方式1>,<继承方式2>,…是三种继承方式:public、private、protected之一
注意:当使用多继承时要注意避免发生二义性
class A{
public:
//……
};
class B{
public:
//……
};
class C:publicA,publicB{
……
};
在定义如下时:
C c1;
c1.print(); //error
解决方法是:c1.A::print();//调用A的或者c1.B::print();//调用B的..在C公有继承A和B,当A和B都公有继承D时,这使得A和B都具有D的公有部分,在C中使用D的公有部分时,编译器就会不确定是调用A的还是调用B的而出现错误
1 派生类构造函数和析构函数的执行顺序
..派生类构造函数的执行顺序:
基类构造函数 —–> 派生类构造函数
..派生类析构函数的执行顺序:
派生类构造函数 —–> 基类构造函数
//派生类的构造函数与析构函数的执行顺序
#include <iostream>
using std::cin;
using std::cout;
using std::endl;
class Base{
public:
Base(){
cout<<"Construction base class.\n";//1
}
~Base(){
cout<<"Destruction base class.\n";//4
}
};
class Derive:public Base{
public:
Derive(){
cout<<"Construction derived class.\n";//2
}
~Derive(){
cout<<"Destruction derived class.\n";//3
}
};
int main()
{
Derive op;
return 0;
}
��当基类的构造函数没有参数(或全部默认值),或没有显示定义构造函数时,那么派生类可以不向基类传递参数,可以不定义构造函数
��当基类含有带参数的构造函数时,派生类必须定义构造函数,以提供把参数传递给基类构造函数的途径
•派生类构造函数的一般格式:
派生类构造函数名(参数表0):基类构造函数名(参数表1){
//…
}
•当派生类中含有对象成员时,其构造函数的一般形式为:
派生类构造函数名(参数表0):基类构造函数名(参数表1),对象成员名1(参数表2),…,对象成员名n(参数表n+1){
//…
}
在定义派生类对象时,构造函数与析构函数的执行顺序为:
..派生类构造函数的执行顺序:
基类构造函数 —–>对象成员 —–> 派生类构造函数
..派生类析构函数的执行顺序:
派生类构造函数 —–> 对象成员 —–> 基类构造函数
//构造函数与析构函数的执行顺序
#include <iostream>
using std::cin;
using std::cout;
using std::endl;
class Base{
private:
int x;
public:
Base(int i){
x = i;
cout<<"构造base类, x="<<x<<endl;
}
~Base(){
cout<<"析构base类, x="<<x<<endl;
}
void show(){
cout<<"x="<<x<<endl;
}
};
class Derive:public Base{
private:
int y;
Base d;
public:
Derive(int i,int j,int k):Base(i),d(j){
y = k;
cout<<"构造derived类, y="<<y<<endl;
}
~Derive(){
cout<<"析构derived类, y="<<y<<endl;
}
};
int main()
{
Derive obj(1,2,3);
obj.show();
return 0;
}
输出结果:
构造base类,x=1
构造base类,x=2
构造derived类,y=3
x=1
析构derived类,y=3
析构base类,x=2
析构base类,x=1
说明
:•如果派生类的基类也是一个派生类,则每个派生类只需负责其直接基类的构造,依次上溯
•由于析构函数是不带参数的,在派生类中是否要定义析构函数与它所属的基类无关,故基类的析构函数不会因为派生类没有析构函数而得不到执行,它们各自是独立的