1 / 19

C++ 程序设计教程

C++ 程序设计教程. 第 8 讲:继承与派生 ( II ). §7.4 派生类的构造和析构函数. 派生类的构造函数 基类的构造函数不被继承,派生类中需要声明自己的构造函数。 声明构造函数时,只需要对本类中新增成员进行初始化,对继承来的基类成员的初始化,自动调用基类构造函数完成。 (隐式调用) 派生类的构造函数需要给基类的构造函数传递参数时,可以在构造函数中调用基类构造函数。 (显式调用). §7.4 派生类的构造和析构函数. 显式调用: class Point { public : Point ( float = 0.0f, float = 0.0f);

langer
Download Presentation

C++ 程序设计教程

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. C++程序设计教程 第8讲:继承与派生(II)

  2. §7.4 派生类的构造和析构函数 • 派生类的构造函数 • 基类的构造函数不被继承,派生类中需要声明自己的构造函数。 • 声明构造函数时,只需要对本类中新增成员进行初始化,对继承来的基类成员的初始化,自动调用基类构造函数完成。 (隐式调用) • 派生类的构造函数需要给基类的构造函数传递参数时,可以在构造函数中调用基类构造函数。 (显式调用)

  3. §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) { … … } 派生类的声明 派生类的实现

  4. 拷贝构造函数 • 若建立派生类对象时调用默认拷贝构造函数,则编译器将自动调用基类的默认拷贝构造函数。 • 若编写派生类的拷贝构造函数,则需要为基类相应的拷贝构造函数传递参数。例如: class Base { public: Base() {…} }; class Derived : public Base { public: Derived (Derived& d) : Base(d) {…} }; 调用Base的构造函数

  5. 继承时的析构函数 • 析构函数也不被继承,派生类自行声明 • 声明方法与一般(无继承关系时)类的析构函数相同。 • 不需要显式地调用基类的析构函数,系统会自动隐式调用。 • 析构函数的调用次序与构造函数相反。 • 如果是显式调用,必须用到虚函数(virtual)

  6. 把派生类对象隐式转换为基类对象 • 派生类对象能作为基类对象处理(即派生类对象指针可强制转换成基类指针),反之不可! • 例如: (引用写法) • Derive d; • Base& refB = d; // 转成基类对象 • // refB 只能作为 Base 对象看待 • Derive& refD = refB; // 转成派生类对象,OK! • Base b; • Derive& refD = b; // 转成派生类对象,ERR!

  7. 把派生类对象隐式转换为基类对象 • 派生类对象能作为基类对象处理(即派生类对象指针可强制转换成基类指针),反之不可! • 例如: (指针写法) • Derive d; • Base* pB = (Base*)&d; // 转成基类对象的指针 • // *pB 只能作为 Base 对象看待 • Derive* pD = (Derive*)pB; // 转成派生类对象指针,OK! • Base b; • Derive* pD = (Derive*)&b; //转成派生类对象指针,ERR!

  8. 基类 派生类指针 派生类 把派生类对象隐式转换为基类对象 • 基类指针或对象与派生类指针或对象混合的四种可能的方式: • 直接用基类指针引用基类对象; • 直接用派生类指针引用派生类的对象; • 用基类指针引用一个派生类的对象; • 用派生类指针引用基类的对象。 基类指针 指针或引用转换,其内容不变!

  9. 构造的顺序是按指定顺序进行的! §复合与继承的比较 • 例: class BirthDate { … }; class TelephoneNumber { … }; class Employee { public: Employee() { … } BirthDate birth; // 作为 Employee 的成员 TelephoneNumber tel; … };

  10. 实例研究 • 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; };

  11. 实例研究 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(); // 提取月薪函数 };

  12. 实例研究 proj1 int employee::employeeNo = 1000; // 员工编号基数为 1000 employee::employee() { individualEmpNo = employeeNo++; // 新员工编号为目前最大号加1 grade = 1; accumPay = 0.0f; } void employee::promote(int increment) { grade += increment; // 升级,提升的级数由increament指定 }

  13. 实例研究 proj2 • class employee { protected: char name[20]; // 姓名 int individualEmpNo; // 个人编号 int grade; // 级别 float accumPay; // 月薪 staticint employeeNo; // 本公司职员目前的最大值 public: employee(); // 构造函数 virtual ~employee(); // 析构函数 voidSetName(char*); // 设置姓名函数 char* GetName(); // 提取姓名函数 … … };

  14. 实例研究 proj2 int employee::employeeNo = 1000; // 员工编号基数为 1000 。。。 。。。 void employee::SetName(char* n) { strcpy(name,n); // 设置姓名 } char* employee::GetName() { return name; // 提取成员姓名 }

  15. 实例研究 proj3 • class employee { protected: char name[20]; // 姓名 int individualEmpNo; // 个人编号 int grade; // 级别 float accumPay; // 月薪 staticint employeeNo; // 本公司职员目前的最大值 public: employee(); // 构造函数 virtual ~employee(); // 析构函数 voidPay() {} // 计算月薪函数 函数为空 voidSetName(char*); // 设置姓名函数 char* GetName(); // 提取姓名函数 … … };

  16. 实例研究 proj3 class technician : public employee // 技术人员类 { private: float hourlyRate; int workHours; public: technician(); void SetWorkHours(int wh); void Pay(); }; void technician::Pay() { accumPay = hourlyRate * workHours; // 计算月薪,按小时计算 }

  17. 实例研究 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; // 计算月薪,按提成比例计算 }

  18. 实例研究 proj3 class manager : public employee // 推销员类 { private: float MonthlyPay; public: manager (); void SetSales(float); void Pay(); }; manager::manager() { MonthlyPay = 8000; } void manager::Pay() { accumPay = MonthlyPay ; // 计算月薪,按提成比例计算 }

More Related