190 likes | 316 Views
C++ 程序设计教程. 第 8 讲:继承与派生 ( II ). §7.4 派生类的构造和析构函数. 派生类的构造函数 基类的构造函数不被继承,派生类中需要声明自己的构造函数。 声明构造函数时,只需要对本类中新增成员进行初始化,对继承来的基类成员的初始化,自动调用基类构造函数完成。 (隐式调用) 派生类的构造函数需要给基类的构造函数传递参数时,可以在构造函数中调用基类构造函数。 (显式调用). §7.4 派生类的构造和析构函数. 显式调用: class Point { public : Point ( float = 0.0f, float = 0.0f);
E N D
C++程序设计教程 第8讲:继承与派生(II)
§7.4 派生类的构造和析构函数 • 派生类的构造函数 • 基类的构造函数不被继承,派生类中需要声明自己的构造函数。 • 声明构造函数时,只需要对本类中新增成员进行初始化,对继承来的基类成员的初始化,自动调用基类构造函数完成。 (隐式调用) • 派生类的构造函数需要给基类的构造函数传递参数时,可以在构造函数中调用基类构造函数。 (显式调用)
§7.4 派生类的构造和析构函数 • 显式调用: classPoint {public: Point (float= 0.0f,float= 0.0f); … … }; classCircle :publicPoint { Circle (floatr=0.0f,floatx=0.0f,floaty=0.0f); … … }; Circle::Circle (floatr,floata,floatb) : 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=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; // 月薪 staticint 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; // 月薪 staticint employeeNo; // 本公司职员目前的最大值 public: employee(); // 构造函数 virtual ~employee(); // 析构函数 voidSetName(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; // 月薪 staticint employeeNo; // 本公司职员目前的最大值 public: employee(); // 构造函数 virtual ~employee(); // 析构函数 voidPay() {} // 计算月薪函数 函数为空 voidSetName(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 ; // 计算月薪,按提成比例计算 }