C++程序设计教程
第 8讲:继承与派生 ( II)
§ 7.4 派生类的构造和析构函数
? 派生类的构造函数
? 基类的构造函数不被继承,派生类中需要声明
自己的构造函数。
? 声明构造函数时,只需要对本类中新增成员进
行初始化,对继承来的基类成员的初始化,自
动调用基类构造函数完成。
(隐式调用)
? 派生类的构造函数需要给基类的构造函数传递
参数时,可以在构造函数中调用基类构造函数。
(显式调用)
§ 7.4 派生类的构造和析构函数
? 显式调用,
class Point
{ public,
Point (float = 0.0f,float = 0.0f);
… … };
class Circle, public Point
{ Circle (float r=0.0f,float x=0.0f,float y=0.0f);
… … };
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!
把派生类对象隐式转换为基类对象
? 基类指针或对象与派生类指针或对象混合的四种可
能的方式,
1,直接用基类指针引用基类对象;
2,直接用派生类指针引用派生类的对象;
3,用基类指针引用一个派生类的对象;
4,用派生类指针引用基类的对象。 基



基类
派生类





指针或引用转换,其内容不变!
§ 复合与继承的比较
? 例,
class BirthDate { … };
class TelephoneNumber { … };
class Employee {
public,
Employee() { … }
BirthDate birth; // 作为 Employee 的成员
TelephoneNumber tel;
… };
构造的顺序是
按指定顺序进
行的!
实例研究
? class Point {
? public,Point (float x=0.0f,float y=0.0f);
? protected,float x,y; };
? class Circle, public Point {
? public,Circle (float r=0.0f,float x=0.0f,
float y=0.0f);
? float area () const;
? protected,float radius; };
? class Cylinder, public Circle {
? public,Cylinder (float h=0.0f,float r=0.0f,
float x=0.0f,float y=0.0f);
? float area () const;
? float volume () const;
? protected,float height; };
实例研究 proj1
? class employee {
protected,
int individualEmpNo; // 个人编号
int grade; // 级别
float accumPay; // 月薪
static int employeeNo; // 本公司职员目前的最大值
public,
employee(); // 构造函数
virtual ~employee(); // 析构函数
void promote(int); // 升级函数
void SetAccumPay(float pa); // 设置月薪函数
int GetIndividualEmpNo(); // 提取编号函数
int GetGrade(); // 提取级别函数
float GetAccumPay(); // 提取月薪函数
};
实例研究 proj1
int employee::employeeNo = 1000;
// 员工编号基数为 1000
employee::employee()
{
individualEmpNo = employeeNo++;
// 新员工编号为目前最大号加 1
grade = 1;
accumPay = 0.0f;
}
void employee::promote(int increment)
{
grade += increment;
// 升级,提升的级数由 increament指定
}
实例研究 proj2
? class employee {
protected,
char name[20]; // 姓名
int individualEmpNo; // 个人编号
int grade; // 级别
float accumPay; // 月薪
static int employeeNo; // 本公司职员目前的最大值
public,
employee(); // 构造函数
virtual ~employee(); // 析构函数
void SetName(char*); // 设置姓名函数
char* GetName(); // 提取姓名函数
… …
};
实例研究 proj2
int employee::employeeNo = 1000;
// 员工编号基数为 1000
。。。 。。。
void employee::SetName(char* n)
{
strcpy(name,n); // 设置姓名
}
char* employee::GetName()
{
return name; // 提取成员姓名
}
实例研究 proj3
? class employee {
protected,
char name[20]; // 姓名
int individualEmpNo; // 个人编号
int grade; // 级别
float accumPay; // 月薪
static int employeeNo; // 本公司职员目前的最大值
public,
employee(); // 构造函数
virtual ~employee(); // 析构函数
void Pay() {} // 计算月薪函数 函数为空
void SetName(char*); // 设置姓名函数
char* GetName(); // 提取姓名函数
… …
};
实例研究 proj3
class technician, public employee
// 技术人员类
{
private,
float hourlyRate;
int workHours;
public,
technician();
void SetWorkHours(int wh);
void Pay();
};
void technician::Pay()
{
accumPay = hourlyRate * workHours;
// 计算月薪,按小时计算
}
实例研究 proj3
class salesman, public employee // 推销员类
{ private,
float CommRate;
float sales;
public,
salesman();
void SetSales(float);
void Pay();
};
void salesman::SetSales(float sl)
{ sales = sl; } // 设置销售额
void salesman::Pay()
{ accumPay = sales * CommRate;
// 计算月薪,按提成比例计算
}
实例研究 proj3
class manager, public employee // 推销员类
{
private,
float MonthlyPay;
public,
manager ();
void SetSales(float);
void Pay();
};
manager::manager()
{ MonthlyPay = 8000; }
void manager::Pay()
{ accumPay = MonthlyPay ;
// 计算月薪,按提成比例计算
}
?