文档介绍:C++程序设计教程
第8讲:继承与派生(II)
§ 派生类的构造和析构函数
派生类的构造函数
基类的构造函数不被继承,派生类中需要声明自己的构造函数。
声明构造函数时,只需要对本类中新增成员进行初始化,对继承来的基类成员的初始化,自动调用基类构造函数完成。
(隐式调用)
派生类的构造函数需要给基类的构造函数传递参数时,可以在构造函数中调用基类构造函数。
(显式调用)
§ 派生类的构造和析构函数
显式调用:
class Point
{ public:
Point (float = , float = );
……};
class Circle : public Point
{ Circle (float r=, float x=, float y=);
……};
Circle::Circle (float r, float a, float b)
: Point (a, b)
{ ……}
派生类的声明
派生类的实现
拷贝构造函数
若建立派生类对象时调用默认拷贝构造函数,则编译器将自动调用基类的默认拷贝构造函数。
若编写派生类的拷贝构造函数,则需要为基类相应的拷贝构造函数传递参数。例如:
class Base
{ public: Base() {…} };
class Derived : public Base
{ public:
Derived (Derived& d) : Base(d) {…}
};
调用Base的构造函数
继承时的析构函数
析构函数也不被继承,派生类自行声明
声明方法与一般(无继承关系时)类的析构函数相同。
不需要显式地调用基类的析构函数,系统会自动隐式调用。
析构函数的调用次序与构造函数相反。
如果是显式调用,必须用到虚函数(virtual)
把派生类对象隐式转换为基类对象
派生类对象能作为基类对象处理(即派生类对象指针可强制转换成基类指针),反之不可!
例如: (引用写法)
Derive d;
Base& refB = d; // 转成基类对象
// refB 只能作为 Base 对象看待
Derive& refD = refB; // 转成派生类对象,OK!
Base b;
Derive& refD = b; // 转成派生类对象,ERR!
把派生类对象隐式转换为基类对象
派生类对象能作为基类对象处理(即派生类对象指针可强制转换成基类指针),反之不可!
例如: (指针写法)
Derive d;
Base* pB = (Base*)&d; // 转成基类对象的指针
// *pB 只能作为 Base 对象看待
Derive* pD = (Derive*)pB; // 转成派生类对象指针,OK!
Base b;
Derive* pD = (Derive*)&b; //转成派生类对象指针,ERR!
把派生类对象隐式转换为基类对象
基类指针或对象与派生类指针或对象混合的四种可能的方式:
直接用基类指针引用基类对象;
直接用派生类指针引用派生类的对象;
用基类指针引用一个派生类的对象;
用派生类指针引用基类的对象。
基类指针
基类
派生类
派生类指针
指针或引用转换,其内容不变!
§复合与继承的比较
例:
class BirthDate { …};
class TelephoneNumber { …};
class Employee {
public:
Employee() { …}
BirthDate birth; // 作为 Employee 的成员
TelephoneNumber tel;
…};
构造的顺序是按指定顺序进行的!
实例研究
class Point {
public: Point (float x=, float y=);
protected: float x, y; };
class Circle : public Point {
public: Circle (float r=, float x=,
float y=);
float area () const;
protected: float radius; };
class Cylinder : public Circle {
public: Cylinder (float h=,float r=,
float x=, float y=);
float area () const;
float volume () const;
protected: float height; };