基类和派生类
类的基本概念与语法
新的类从已有类那里得到已有的特性,称为类的继承。
在已有类的基础上新增自己的特性而产生新类的过程称为类的派生。
基类和派生类的概念
被继承的类称为基类(父类)
派生出的新类称为派生类(子类)
直接基类:直接参与 派生出的某类的基类。
间接基类:基类的基类 甚至更高层的基类。
继承和派生的目的
继承的目的——代码重用
派生的目的——新的问题出现时,对原有的程序进行改造
派生类定义的语法
class 派生类名: 继承方式 基类名1, 继承方式 基类名2,... 继承方式 基类名n
{
派生类成员的声明;
}
单继承时派生类的举例
单继承:派生类只从一个直接基类继承
class Derived:public Base{
public:
Derived();
~Derived();//构造函数和析构函数都不能从基类继承
};
//派生类名:Derived 继承方式:public 基类名:Base
//还可以增加其他新增的数据成员和成员函数
单继承时,派生类得到了单个基类的特征
多继承时派生类的举例
多继承:派生类从多个直接基类继承
class Derived:public Base1,Private Base2{
public:
Derived();
~Derived();//构造函数和析构函数都不能从基类继承
};
//派生类:Derived 继承方式:public 基类名1 Base1, 继承方式:private Base2
//还可以增加其他新增的数据成员和成员函数
多继承时,派生类得到了多个基类的特征。
派生类的构成
- 吸收的基类成员——基类中除构造函数和析构函数之外的所有成员
- 改造过的基类成员——定义和某基类成员同名的成员,隐藏或覆盖了外层同名的成员
- 添加新的成员——使派生类在功能上有所发展
访问控制
类的继承方式
继承方式规定了如何访问从基类继承的成员。
不同继承方式的影响体现在:
- 在派生类的内部,派生类成员对基类成员的访问
- 在派生类的外部,通过派生类对象对基类成员的访问
3种不同继承方式
- 公有继承(public)
- 私有继承(private)【默认继承方式,如果不显式指明继承发生,即表示继承方式为private】
- 保护继承(protected)
公有继承
公有继承是最常用的继承方式。
访问方式
基类的public和protected成员:访问属性在派生类中保持不变
基类的private成员:不可以直接访问(仅可以通过基类的公有访问接口,即公有函数成员进行访问)
访问权限
在派生类内部,比如派生类中的成员函数:可以直接访问基类中的public和protected成员,但不能直接访问基类的private成员。
在派生类的外部,通过派生类对象:只能访问其public成员
class Point{ public: void initPoint(float x=0,float y=0){ this->x=x; this->y=y; } void move(float offX,float offY){ x+=offX; y+=offY; } float getX()const{ return x; } float getY()const{ return y; } private://基类的私有成员 float x,y; };
class Rectangle:public Point{ public://新增公有函数成员 void initRectangle(float x,float y,float w,float h){ initPoint(x,y);//调用基类的公有函数访问基类的私有成员 this->w=w; this->h=h; } float getH(){ return h; } float getW(){ return w; } private://新增的私有数据成员 float w,h; };
#include <iostream> #include "Point.h" #include "Rectangle.h" using namespace std; int main(){ Rectangle rect; rect.initRectangle(2,3,20,10); rect.move(3,2); cout<<"The data of rect(x,y,w,h):"<<endl; /*调用从基类继承来的getX(),getY()函数*/ cout<<rect.getX()<<","<<rect.getY()<<","<<rect.getW()<<","<<rect.getH()<<endl; return 0; }
如果在主函数中将
cout<<rect.getX()<<","<<rect.getY()<<","<<rect.getW()<<","<<rect.getH()<<endl;
改为
cout<<rect.x<<","<<rect.y<<","<<rect.getW()<<","<<rect.getH()<<endl;
编译器就会报错【我使用的是devC++】
![]()
![]()
原因是x,y是Point类的私有成员,派生类Rectangle无法直接访问
如果将Point类的x,y设为公有
class Point{ public: void initPoint(float x=0,float y=0){ this->x=x; this->y=y; } void move(float offX,float offY){ x+=offX; y+=offY; } float getX()const{ return x; } float getY()const{ return y; } float x,y;//x,y设为公有成员 };
编译就可以通过
私有继承
最严格的一种继承方式
访问控制
基类的public和protected成员:都以private身份出现在派生类中,基类的private成员:不可直接访问。(仅通过基类的公有访问接口,即公有成员函数进行访问)
访问权限
在派生类的内部,比如派生类中的成员函数中:可以直接访问基类中的public和protected成员,但不能直接访问基类中的private成员。
在派生类的外部,通过派生类的对象:不能直接访问从基类继承的任何成员(因为它们在基类中的访问控制都变为私有)
例
class Point{ public: void initPoint(float x=0,float y=0){ this->x=x; this->y=y; } void move(float offX,float offY){ x+=offX; y+=offY; } float getX()const{ return x; } float getY()const{ return y; } private://基类的私有成员 float x,y; };
class Rectangle:private Point{//以私有方式继承 public://新增公有函数成员 void initRectangle(float x,float y,float w,float h){ initPoint(x,y);//调用基类的公有函数访问基类的私有成员 this->w=w; this->h=h; } float getH(){ return h; } float getW(){ return w; } //新的访问接口,公有,可类外调用 /*重新定义之后变为派生类的公有成员*/ void move(float offX,float offY){ Point::move(offX,offY); } float getX()const{ return Point::getX(); } float getY()const{ return Point::getY(); } private://新增的私有数据成员 float w,h; };
#include <iostream> #include "Point.h" #include "Rectangle.h" using namespace std; int main(){ Rectangle rect; rect.initRectangle(2,3,20,10); rect.move(3,2); cout<<"The data of rect(x,y,w,h):"<<endl; /*调用派生类成员函数的getX(),getY()*/ cout<<rect.getX()<<","<<rect.getY()<<","<<rect.getW()<<","<<rect.getH()<<endl; }
保护继承
访问控制
基类的public和protected成员:都以protected身份出现在派生类中。
基类的private成员:不可直接访问(仅通过基类的公有访问接口,即公有成员函数进行访问)
访问权限
在派生类的内部 ,比如派生类中的成员函数中:可以直接访问基类中的public和protected成员,但不能直接访问基类的private成员。
在派生类的外部,有可能访问从基类继承的public和protected成员。(它们在派生类中的属性都是protected,可以在该派生类的子类中访问)
保护成员
特点
对建立其所在类对象的模块来说,它与私有成员的性质相同,不能通过对象名来访问。
对其派生类来说,它与public对象相同,可以访问,
保护成员用在何种场合?
基类和派生类都是自己写的。
例
class A{ protected: int x;//类A中的保护成员 }; int main(){ A a; a.x=5;//错误,和类A的私有成员相同,不能在类A之外访问 }
class A{ protected: int x; }; class B:public A{ public: void f(); }; void B::f(){ x=5;//正确,类B是类A的派生类,可以在类B中访问类A的保护成员 }
多继承举例
#include <iostream>
using namespace std;
class A{
public:
void setA(int x){
a=x;
}
void showA()const{
cout<<a<<endl;
}
private:
int a;
};
class B{
public:
void setB(int x){
b=x;
}
void showB()const{
cout<<b<<endl;
}
private:
int b;
};
class C:public A,private B{
public:
void setC(int x,int y,int z){
setA(x);
setB(y);
c=z;
}
void showC()const{
cout<<c<<endl;
}
private:
int c;
};
int main(){
C obj;
obj.setA(5);
obj.showA();
obj.setC(6,7,9);
//obj.setB(6);//错误
//obj.showB();//错误
return 0;
}
对于注释的两行语句,因为是私有继承的,所以派生类无法访问,执行这两句就会报错。