一、继承的概念
继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段,它可以让程序员在保持原有类特性的基础上进行扩展,增加功能,这样产生新的类,称派生类,而被继承的类则称为基类。
//A:基类
class A{
public:
int _b;
};
//B:派生类
class B : public Base{
public:
int _d;
};
通过继承的方式,可以将基类的成员都变为了派生类的一部分。
二、继承方式
派生类的定义为:
派生类类名 : 继承方式 : 基类
其中继承方式有三种,分别为:public、protected、private
1、public继承
公有继承:用该关键字修饰的成员表示公有成员,该成员不仅可以在类内可以被访问,在类外也是可以被访问的,是类对外提供的可访问接口。
公有继承时,基类的公有成员和保护成员在派生类中属性不变,但私有成员不可直接访问。基类成员对派生类对象的可见性为:基类的公有成员可见,保护成员和私有成员不可见,即通过派生类的对象只能访问基类的public成员。
所以,在公有继承时,派生类的对象可以直接访问基类中的公有成员,派生类的成员函数可以直接访问基类中的公有成员和保护成员。
class A{
public:
int _a;
protected:
int _a1;
private:
int _a2;
};
//公有继承
class B : public Base{
public:
int _a;
protected:
int _a1;
private: //不可访问
int _a2;
};
2、protected继承
保护继承:用该关键字修饰的成员表示保护成员,保护成员在类体外同样是隐藏状态,但是对于该类的派生类来说,相当于公有成员,在派生类中可以被访问。
在保护继承中,基类公有成员和保护成员都以保护成员出现在派生类中,但基类私有成员仍然不能被直接访问。保护成员在派生类中被视为公有成员,在类外被视为私有成员。
基类private成员在派生类中是不能被访问,如果基类成员不想在类外直接被访问,但需要在派生类中能 访问,就定义为protected。
class A{
public:
int _a;
protected:
int _a1;
private:
int _a2;
};
//保护继承
class B : protected Base{
protected:
int _a;
int _a1;
private: //不可访问
int _a2;
};
3、provite继承
私有继承:用该关键字修饰的成员表示私有成员,该成员仅在类内可以被访问,在类体外是不可访问状态。
当继承方式为私有继承时,基类的公有成员和保护成员都以私有成员出现在派生类中,同样私有成员在派生类中不可直接访问。此时派生类成员函数可以调用基类公有成员和保护成员,但是在类外部不可使用任何基类成员。
class A{
public:
int _a;
protected:
int _a1;
private:
int _a2;
};
//私有继承
class B : private Base{
private:
int _a;
int _a1;
//不可访问
int _a2;
};
三、基类和派生类的赋值
1、派生类对象 可以赋值给基类的对象 / 基类的指针 / 基类的引用。这里的说法叫切片或者切 割。意味着把派生类中父类那部分切来赋值过去。
2、基类对象不能赋值给派生类对象 。
3、基类的指针可以通过强制类型转换赋值给派生类的指针。但是必须是基类的指针是指向派生类对象。
class A{
public:
int _a;
int _b;
};B
class B : public A{
public:
int _c;
};
void test(){
B pB;
// 1.派生类对象可以赋值给基类对象/指针/引用
A pA = pB;
A* pA = &pB;
A& pA = pB;
//2.基类对象不能赋值给派生类对象
pB = pA;
// 3.基类的指针可以通过强制类型转换赋值给派生类的指针
pp = &pA;
B* p1 = (B*)pp;
p1->_c=1;
}
四、派生类的默认成员函数
- 派生类的构造函数必须调用基类的构造函数初始化基类的那一部分成员。如果基类没有默认的构造函数,则必须在派生类构造函数的初始化列表阶段显示调用。
- 派生类的拷贝构造函数必须调用基类的拷贝构造完成基类的拷贝初始化。
- 派生类的operator=必须要调用基类的operator=完成基类的赋值。
- 派生类的析构函数会在被调用完成后自动调用基类的析构函数清理基类成员。因为这样才能保证派生类对象先清理派生类成员再清理基类成员的顺序。
- 派生类对象初始化先调用基类构造再调派生类构造。
- 派生类对象析构清理先调用派生类析构再调基类的析构。