一、通过继承,我们可以用原来的数据类型来定义一个新的数据类型,定义的新类型既有原来数据中的成员,也能自己添加新的成员
我们一般把原来的数据类型称为基类或者父类,新的数据类型为派生类,或者子类,在本篇博客中Base为基类,Deriver为派生类
继承的本质是代码复用
如上图所示继承与派生的关系
class Base
{
public:
Base(int a = 0) :ma(a){}
void Show()
{
std::cout << "Base::Show : ma " << ma << std::endl;
}
static void Show1()
{
std::cout << "hello world" << std::endl;
}
public:
int ma;
};
class Derive : public Base
{
public:
Derive(int b) :mb(b){}
void Print()
{
std::cout << "Derive::Print : mb " << mb << std::endl;
}
private:
int mb;
};
1、派生类的内存布局
2、派生类继承了基类的什么?
不能继承的:
(1)构造和析构
(2)有缘关系
派生类继承了基类中除了构造和析构以外所有的成员变量和成员方法、类型和作用域
3、继承方式
(1)公有继承 (public继承)
公有继承的特点是基类的公有成员和保护成员作为派生类的成员时,它们都保持原有的状态,而基类的私有成员仍然为私有的,不能被这个派生类的子类所访问。
(2)保护继承(proteced继承)
保护继承的特点是基类的所有公有成员和保护成员都作为派生类的保护成员,并且只能被它的派生类成员函数或友元函数访问,基类的私有成员仍然为私有的。
(3)私有继承(private继承)
私有继承的特点是基类的公有成员和保护成员都作为派生类的私有成员,并且不能被这个派生类的子类所访问。
4、类之间的关系
(1)组合 has_a a part of
(2)继承 is_a a kind of
(3)代理
5、派生类的构造和析构方式
当基类中没有默认的构造函数时,在派生类中的构造函数初始化列表中应当指明基类的构造方式
(1)构造方式
派生类对象在构造时先构造基类部分,在构造派生类部分
(2)析构方式
派生类对象在析构时,先析构派生类部分,在析构基类部分
6、基类和派生类指针或引用的相互指向或引用
class Base
{
public:
Base(int a) :ma(a){}
void Show()
{
std::cout << "Base::Show ==> ma: " << ma << std::endl;
}
void Show(int flag)
{
std::cout << "Base::Show(int) ==> hello world!" << std::endl;
}
protected:
int ma;
};
class Derive : public Base
{
public:
Derive(int b) :mb(b), Base(b){}
void Show()
{
std::cout << "Derive::Show ==> mb: " << mb << std::endl;
}
private:
int mb;
};
int main()
{
Base b(10);
Derive d(20);
Base* pb = &d; //基类的指针指向派生类对象 v
Derive* pd = &b; //派生类的指针指向基类对象 x
Base& rb = d; //基类的引用引用派生类对象 v
Derive& rd = b; //派生类的引用引用基类对象 x
return 0;
}
基类的指针或引用可以指向或引用派生类对象
不允许派生类的指针或引用指向或引用基类对象
如果派生类指针指向基类对象,派生类指针可以访问派生类的成员变量或者成员函数,但是基类中没有,所以访问会出错