继承:在定义一个新的类B时,如果该类与某个已有的类A相似(指的是B拥有A的全部特点),那么就可以把A作为一个基类,而把B作为基类的一个派生类(也称子类)。
派生类是通过对基类进行修改和扩充得到的。在派生类中,可以扩充新的成员变量和成员函数。派生类一经定义后,可以独立使用,不依赖于基类。
派生类拥有基类的全部成员函数和成员变量,不论是private、 protected、 public 。但在派生类的各个成员函数中,不能访问基类中的private成员
class 派生类名: public 基类名
{
};
派生类对象的体积,等于基类对象的体积,再加上派生类对象自己的成员变量的体积。 在派生类对象中,包含着基类对象,而且基类对象的存储位置位于派生类对象新增的成员变量之前。
继承:“ 是”关系。
- 基类 A, B是基类A的派生类。
- 逻辑上要求:“一个B对象也是一个A对象”。
复合:“ 有”关系。
- 类C中“有” 成员变量k, k是类D的对象,则C和D是复合关系
- 一般逻辑上要求:“ D对象是C对象的固有属性或组成部分”。
假如定义一个Master类,一个Dog类,Master最多有10只狗,狗最多有1个主人,如果像下面这样写:
class Dog;
class Master
{
Dog dogs[10];
};
class Dog
{
Master m;
};
错误!循环定义了,正确定义方法如下:
class Master; //Master必须提前声明
class Dog {
Master * pm;
};
class Master {
Dog * dogs[10];
};
基类的private成员: 可以被下列函数访问
• 基类的成员函数
• 基类的友员函数
基类的public成员: 可以被下列函数访问
• 基类的成员函数
• 基类的友员函数
• 派生类的成员函数
• 派生类的友员函数
• 其他的函数
基类的protected成员: 可以被下列函数访问
• 基类的成员函数
• 基类的友员函数
• 派生类的成员函数可以访问当前对象的基类的保护成员
小结一下,private只有自己和朋友能访问;protected只有自己、朋友和儿子能访问;public都可以被访问。
class Father {
private: int nPrivate; //私有成员
public: int nPublic; //公有成员
protected: int nProtected; // 保护成员
};
class Son : public Father {
void AccessFather () {
nPublic = 1; // ok;
nPrivate = 1; // wrong
nProtected = 1; // OK, 访问从基类继承的protected成员
Son f;
f.nProtected = 1; //wrong, f不是当前对象,即不是this
}
};
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
return 0;
}
派生类对象包含基类对象,执行派生类构造函数之前,先执行基类的构造函数。
在派生类的构造方法需要交代基类对象初始化的方法,具体形式:
构造函数名(形参表): 基类名(基类构造函数实参表)
{ }
比如:
class Bug {
private :
int nLegs; int nColor;
public:
Bug (int l, int c): nLegs(l), nColor(c) { }
};
class FlyBug: public Bug {
int nWings;
public:
//正确的FlyBug构造函数:
FlyBug(int legs, int color, int wings):Bug(legs, color) { nWings = wings; }
};
派生类的构造函数的调用顺序:
1. 调用 基类 的构造函数。初始化派生类对象中从基类继承的成员。
2. 调用成员对象类的构造函数。初始化派生类对象中成员对象。
3. 调用自身的构造函数。
派生类析构函数的调用顺序
1. 调用自身的析构函数
2. 调用成员对象类 的析构函数
3. 调用基类的析构函数
总之,无论是成员对象还是基类对象,构造函数都是从里到外开始执行的,析构函数都是从外到里开始执行的。就像生活中做一台电脑和拆一台电脑一样。
其实很简单,我们可以说猫是动物,却不能说动物是猫,就这样。
class base { };
class derived : public base { };
base b;
derived d;
如果派生方式是 private或protected,则上述三条不可行。