继承与派生
关于继承与派生
在面向对象中,该技术强调软件的可重用性,而在C++中可重用性便是通过 “继承” 这一机制来实现的。一个新类从已有的类那里获得其已有的特性,这种现象称为类的继承。同时继承也是C++ 和 C 语言最重要的区别之一。
派生类继承了基类的所有数据成员和成员函数,并可以对成员作必要的增加或者调整,一个基类可以派生出多个派生类,每一个派生类又可以作为基类再派生出新的基类,因此基类和派生类是相对而言的,而一代代的派生下去就形成了类的继承层次结构。同样,类的每一次派生都继承了其基类的基本特征。
一个派生类只从一个基类派生,这称为单继承,这种继承关系所形成的层次是一个树形结构(一个基类可以派生多个子类,一个子类可以由 多级 基类派生而来。);而一个派生类有两个或者多个基类的称为多重继承
基类和派生类之间的关系可以形容为:派生类是基类的具体化,基类是派生类的抽象。
继承有什么用处:
有许多基类是被程序的其他部分所使用的,这些程序要求保留原有的积累不被破坏,使用继承是建立新的数据类型,它继承了基类的所有特征,但不改变基类本身。基类的名称。构成和访问属性都不会被改变,也不会影响其他程序所使用。
用户往往是得不到基类的源代码。如果想修改已有的类,必须掌握类的声明和类的实现(成员函数的定义)的源代码。但是,如果使用类库,用户是无法知道成员函数的代码的,因此也就无法对基类进行修改,保证了基类的安全。
在类库中,一个基类可能已被指定与用户所需的多种组件建立了某种关系,因此在类库中的基类是不允许修改的(即使知道了源代码,也不允许修改)。
实际上有许多基类并不是从已有的其他程序中选取来的,而是专门作为基类设计的。有些基类可能并没有什么独立的功能,只是一个框架,或者说是抽象类。用户根据需要设计了一批能适用于不同用途的通用类,目的是建立通用的数据结构,以便用户在此基础上添加各种功能,建立各种功能的派生类。
基类(或父类):被继承的原有类
直接基类:直接参与派生出某类的基类
间接基类: 基类的基类甚至更高层的基类
派生类(或子类): 派生出的新类 包括三部分
1)吸收基类的成员:默认情况下派生类包含了基类除了构造函数和析构函数之外的所有成员,但是C++11规定可以用using关键字将构造函数也继承过来。
2)改造基类的成员:如果派生类声明了一个和基类成员同名的新成员,这样基类同名的成员就被覆盖了。
3)添加新的成员:派生类在功能上有所发展。
单继承(派生类只从一个直接基类继承)时派生类的定义:
class 派生类名:继承方式 基类名
{
新增成员声明;
}
多继承时派生类的定义:
class 派生类名:继承方式1 基类名1,继承方式2 基类名2,…
{
成员声明;
}
注意:每一个“继承方式”,只用于限制对紧随其后之基类的继承。
三种继承方式:公有继承,私有继承和保护继承
公有继承(public)
1)继承的访问控制
基类的public和protected成员:访问属性在派生类中保持不变;
基类的private成员:不可直接访问。
2)访问权限
派生类中的成员函数:可以直接访问基类中的public和protected成员,但不能直接访问基类的private成员;
通过派生类的对象:只能访问public成员。
3)公有派生类对象可以被当作基类的对象使用,反之则不可。
派生类的对象可以隐含转换为基类对象;
派生类的对象可以初始化基类的引用;
派生类的指针可以隐含转换为基类的指针。
通过基类对象名、指针只能使用从基类继承的成员,派生类新增的成员就不能使用了。
公有继承
class Rectangle:public Point//派生类定义部分 { public://新增公有函数 void initRectangle(float x, float y, float w, float h) { initPoint(x, y);//调用基类公有函数 this->w = w; this->h = h; } ~Rectangle(); float getH() const { return h; } float getW() const { return w; } private: float h, w;//新增私有数据成员 }; 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; } ~Rectangle(); void move(float offx, float offy) { Point::move(offx, offy); } float getX() const { return Point::getX(); } float getY()const { return Point::getY(); } float getH() const { return h; } float getW() const { return w; } private: float h, w;//新增私有数据成员 }; Rectangle::~Rectangle() { }