1 继承的概念
在定义一个新的类 B 时,如果该类与某个已有的类 A 相似(指的是 B 拥有 A 的全部特点),那么就可以把 A 作为一个基类,而把 B 作为基类的一个派生类(也称子类)。
2 派生类的写法
class 派生类类名:public 基类类名
{
...
};
3 继承实例程序:学籍管理
#include
#include
using namespace std;
class CStudent
{
private:
string name; //姓名
string id; //学号
char gender; //性别,‘F’代表女,‘M’代表男
int age;
public:
void PrintInfo();
void SetInfo(const string & name_,const string & id_,int age_,char gender_);
string GetName(){ return name; }
};
void CStudent::PrintInfo()
{
cout<<"Name:"<
1 C++类之间的关系
复合关系使用的例子 :
class CPoint
{
double x,y;
friend class CCircle;
//便于 CCircle 类操作其圆心,因为 CPoint 类的成员对象是其私有的
};
class CCircle
{
double r;
CPoint center;
};
小区养狗的管理程序:两个类:主人类、狗类。狗只有一个主人,而每个业主最多可拥有10条狗。
class CDog;
class CMaster
{
CDog dogs[10];
};
class CDog
{
CMaster m;
};
上面这种处理方法是错误的,循环定义。CDog 类和CMaster 类的字节大小是多少?
另一种写法:为“狗”类设一个“业主”类的成员变量,为“业主”类设一个“狗”类的对象指针数组。
class CDog;
class CMaster
{
CDog * dogs[10];
};
class CDog
{
CMaster m;
};
该种写法避免了循环定义,但还是错误的。无法维护不同的狗中主人信息一致性的问题。如果改变了一条狗中的主人信息,另一条狗中的主人信息也应进行相应的改变。而这种写法无法做到。
第三种写法,凑合的写法。 为“狗”类设一个“业主”类的对象指针,为“业主”类设一个“狗”类的对象数组。
class CMaster; //CMaster必须提前声明,不能先写CMaster类,后写CDog类
class CDog
{
CMaster * m;
};
class CMaster
{
CDog dogs[10];
};
这种写法有两点不好的地方:一、狗不是主人的一部分,狗不是主人的固有属性。二、“狗”类失去了自由。对“狗”对象进行操作时要通过“主人”对象。
正确的写法: 为“狗”类设一个“业主”类的对象指针,为“业主”类设一个“狗”类的对象指针数组。
class CMaster; //CMaster必须提前声明,不能先写CMaster类,后写CDog类
class CDog
{
CMaster * m;
};
class CMaster
{
CDog * dogs[10];
};
1 覆盖的概念
派生类可以定义一个和基类成员同名的成员,这叫覆盖。在派生类中访问这类成员时,缺省的情况是访问派生类中定义的成员。要在派生类中访问由基类定义的同名成员时,要使用作用域符号 :: 。
基类和派生类不要定义同名的成员变量。
2 保护成员
基类的 private 成员可以被下列函数访问:
基类的 public 成员可以被下列函数访问:
基类的 protected 成员可以被下列函数访问:
#include
using namespace std;
class Father
{
private:
int nPrivate; //私有成员
public:
int nPublic; //公有成员
protected:
int nProtected; //保护成员
};
class Son:public Father
{
void AccessFather()
{
nPublic = 1; //ok
// nPrivate = 1; //error
nProtected = 1; //ok ,访问当前对象从基类继承的 protected 成员。
Son f;
// f.nProtected = 1; //error。f 不是当前对象
}
};
int main()
{
Father f;
Son s;
f.nPublic = 1; //ok
s.nPublic = 1; //ok
// f.nProtected = 1; //error
// f.nPrivate = 1; //error
// s.nProtected = 1; //error
// s.nPrivate = 1; //error
system("pause");
return 0;
}
在创建派生类的对象时,需要调用基类的构造函数:初始化派生类对象中从基类继承的成员。在执行一个派生类的构造函数之前,总是先执行基类的构造函数。
调用基类构造函数的两种方式:
派生类的析构函数被执行时,执行完派生类的析构函数后,自动调用基类的析构函数。
封闭派生类对象(含有成员对象)的构造函数执行顺序:
在封闭派生类对象消亡时:
#include
using namespace std;
class Bug
{
private:
int nLegs;
int nColor;
public:
int nType;
Bug(int legs, int color);
void PrintBug(){ };
};
Bug::Bug(int legs, int color)
{
nLegs = legs;
nColor = color;
}
class FlyBug:public Bug //FlyBug 是 Bug 的派生类
{
int nWings;
public:
FlyBug(int legs,int color, int wings);
};
//错误的派生类 FlyBug 构造函数的写法
//FlyBug::FlyBug(int legs,int color, int wings)
//{
// nLegs = legs; //不能访问
// nColor = color; //不能访问
// nType = 1; //ok
// nWings =wings;
//}
//正确的 FlyBug 构造函数
FlyBug::FlyBug(int legs,int color, int wings):Bug(legs,color) //派生类的初始化列表里直接初始化基类的 Bug 对象
{
nWings = wings;
}
int main()
{
FlyBug fb(2,3,4);
fb.PrintBug();
fb.nType = 1;
// fb.nLegs = 2; //error.nLegs是基类的私有成员变量,派生类不能访问
system("pause");
return 0;
}
class base { };
class derived:public base { };
base b;
derived d;
如果派生方式是 private 或 protected ,则上述三条不可行。
2 直接基类和间接基类
在声明派生类时,只需要列出它的直接基类。
派生类沿着类的层次自动向上继承它的间接基类。
派生类的成员包括: