好文档就是一把金锄头!
欢迎来到金锄头文库![会员中心]
电子文档交易市场
安卓APP | ios版本
电子文档交易市场
安卓APP | ios版本

c程序设计基础第八章继承和派生.ppt

106页
  • 卖家[上传人]:ni****g
  • 文档编号:580455106
  • 上传时间:2024-08-29
  • 文档格式:PPT
  • 文档大小:1.90MB
  • / 106 举报 版权申诉 马上下载
  • 文本预览
  • 下载提示
  • 常见问题
    • C++程序程序设计基基础第第8章章 继承与派生承与派生北京北京邮电大学信通院大学信通院方莉方莉 第第8 8章章 继承与派生承与派生v类具有具有封装性、封装性、继承性和多承性和多态性性,使得,使得软件开件开发者可以把者可以把类设计成相成相对独立的模独立的模块,像一个个,像一个个积木木块,便于重用便于重用v类的的继承性承性是是实现软件重用件重用的一种重要形式的一种重要形式v本章将学本章将学习::§继承和派生的概念,承和派生的概念,继承方式;承方式;§派生派生类的构造函数和析构函数;的构造函数和析构函数;2 第第8 8章章 继承与派生承与派生8.1 8.1 继承的概念承的概念8.2 8.2 定定义基基类和派生和派生类8.3 8.3 构造函数和析构函数构造函数和析构函数8.4 8.4 转换与与继承承3 8.1 8.1 继承的概念承的概念- -例子例子自行自行车Bicycle山地山地车 Mountain Bike竞速自行速自行车 Racing Bike双人自行双人自行车 Tandem Bike4 8.1 8.1 继承的概念承的概念- -例子例子v山地山地车继承承了自行了自行车的特征的特征山地山地车 ““派生派生””于于 自行自行车5 8.1 8.1 继承的概念承的概念 v类的的继承承是在是在现有有类的基的基础之上,之上,创建新建新类的机制的机制。

      称称现有的有的类为基基类,,新建立的新建立的类为派生派生类§派生派生类继承了基承了基类的属性和行的属性和行为§派生派生类是基是基类的特殊情况的特殊情况v基基类是是共性的抽象共性的抽象,派生,派生类是是个性的体个性的体现v不必从不必从““草稿草稿””开始开始创建特殊的程序建特殊的程序对象v继承是承是处理理““特殊情况特殊情况””的面向的面向对象象编程机制 6 Bike基类Tandem Bike派生类派生于int Wheel;bool Run();int Wheel;bool Run();int Seat;父类子类 从基类继承8.1 8.1 继承的概念承的概念 7 第第8 8章章 继承与派生承与派生8.1 8.1 继承的概念承的概念8.2 8.2 定定义基基类和派生和派生类8.3 8.3 构造函数和析构函数构造函数和析构函数8.4 8.4 转换与与继承承8 8.2 8.2 定定义基基类和派生和派生类v定定义派生派生类时要声明要声明继承方式承方式,三种,三种继承方式:承方式:§publicpublic§ProtectedProtected§private private v访问控制受控制受继承方式的影响;承方式的影响;v不同不同继承方式的影响主要体承方式的影响主要体现在:在: §派生派生类成成员对基基类成成员的的访问控制;控制; §派生派生类对象象对基基类成成员的的访问控制;控制;v继承承导致一种特殊的致一种特殊的语法法现象:象:同名覆盖同名覆盖。

      9 8.2.1 8.2.1 简单的的继承和派生承和派生v问题:想在屏幕上画出正三角形、矩形或:想在屏幕上画出正三角形、矩形或圆形形v方法一:方法一:结构化方法构化方法§DrawTri (int x, int y, char color, int side);DrawTri (int x, int y, char color, int side);§DrawRect (int x, int y, char color, int length, int width)DrawRect (int x, int y, char color, int length, int width)§DrawCircle(int x, int y, char color, int Radius)DrawCircle(int x, int y, char color, int Radius)v方法二:面向方法二:面向对象?象?§class circle class circle 圆形形§class rectangle class rectangle 矩形矩形§class triangle class triangle 三角形三角形§基基类:: class shapeclass shape•色彩色彩 colorcolor•位置位置 (x, y)(x, y)shapecirclerectangletriangle泛化?10 v图形形§circle circle 圆形形§rectangle rectangle 矩形矩形§triangle triangle 三角形三角形 基基类称称为父父类派生派生类称称为子子类 shapecirclerectangletrianglev分分层次的次的设计类使模使模块划分更合划分更合理;便于理;便于软件系件系统的的设计和和维护。

      8.2.1 8.2.1 简单的的继承和派生承和派生11 class Shape{private: int m_x,m_y; //位置位置 char m_color; //颜色色public: Shape(); void setposition(int x, int y); void setcolor(char color); int getx(); int gety(); char getcolor();};例例1-1-定定义基基类shapeshape成成员函数的分函数的分类::1.构造函数构造函数2.设置属性置属性值3.读取属性取属性值12 class Triangle: public Shape {public:Triangle(int x, int y, char color='R', float slen = 1);float GetSideLength() const;void SetTriangle(int x, int y, char color, float slen);void Draw();private:float m_SideLength;};例例1-1-定定义派生派生类( (等等边三角形三角形类) )成成员函数的分函数的分类::1.构造函数构造函数2.设置属性置属性值3.读取属性取属性值13 派生派生类的定的定义格式格式class class 派生派生类名:名:继承方式承方式 基基类名名{ { public: public: // //派生派生类公有成公有成员…… private:private: // //派生派生类私有成私有成员…… } }派生派生类只有只有一个直接基一个直接基类为单继承承8.2.2 8.2.2 定定义派生派生类14 class 派生派生类名:名:继承方式承方式 基基类名名1, … 继承方式承方式 基基类名名n { public: //派生派生类公有成公有成员… private: //派生派生类私有成私有成员… }有多个基有多个基类派生派生类有有多个基多个基类为多多继承承8.2.2 8.2.2 定定义派生派生类15 u例如例如: : 已有基已有基类b1b1和和b2b2,,定定义派生派生类derivederive,其中包括:,其中包括:u私有整型成私有整型成员 newIntnewInt,,u公有函数成公有函数成员 intint newFunnewFun()(),,u私有函数成私有函数成员 intint max(intmax(int a, a, intint b) b);;u写出写出类derivederive的定的定义8.2.2 8.2.2 定定义派生派生类class derive : public b1 , private b2{private: int newInt;public: void newFun();private:int max( int a, int b );};16 v类的的继承方式是承方式是派生派生类对基基类成成员的的继承方式承方式。

      v类的的继承承方方式式影影响响类外外模模块对于于派派生生类从从基基类继承承来来的的成成员的的访问权限限v每一个每一个“继承方式承方式”,只用于限制,只用于限制对紧随其后随其后之基之基类的的继承class derive : public b1 , private b2{private: int newInt;public: void newFun();private:int max( int a, int b );};8.2.2 8.2.2 定定义派生派生类17 class base{…… };class deriver1:public base{ …… };class deriver2:public deriver1{…… }•父父类被称被称为子子类的的直直接基接基类 •父父类的父的父类或更高或更高层次的父次的父类被称被称为这个个子子类的的间接基接基类 8.2.2 8.2.2 定定义派生派生类18 class Shape:{public:Shape(int x=0, int y=0, char c = 'R');int GetX() const;void SetX( int x);int GetY() const;void SetY( int x);char GetColor() const;void SetColor(char c);protected:char m_color;int m_x;int m_y; };例例2-2-图形形类及其派生及其派生类的声明的声明19 class Circle : public Shape {public:Circle(int x, int y, float r=1, char color='R');void SetCircle(int x, int y, float r, char color); float GetRadius () const; void Draw();private:float m_Radius;};例例2-2-图形形类及其派生及其派生类的声明的声明20 class Triangle: public Shape {public:Triangle(int x, int y, char color='R', float slen = 1);void SetTriangle(int x, int y, char color, float slen);float GetSideLength() const; void Draw();private:float m_SideLength;};例例2-2-图形形类及其派生及其派生类的声明的声明21 class Rectangle: public Shape{public:Rectangle(int x, int y, char color, int length=10, int width=10);void SetRectangle (int x, int y, char color, int length, int width); int GetWidth() const;int GetHeight() const;void Draw();private:int m_Width;int m_Length;};例例2-2-图形形类及其派生及其派生类的声明的声明22 •派生派生类的成的成员包括:(包括:(1 1))继承基承基类的成的成员,(,(2 2)派生)派生类定定义时声声明的成明的成员。

      •派生派生类自己增加的成自己增加的成员,完成两个,完成两个需求:需求:(1)(1)修改基修改基类成成员,(,(2 2)描)描述新的特征或方法述新的特征或方法 m_color;m_x; m_y;GetX();SetX();GetY();SetY();GetColor();SetColor();m_Radius;GetRadius () SetCircle();Draw(); 从基从基类继承的承的成成员派生派生类增加的增加的成成员23 8.2.3 8.2.3 访问控制和控制和继承关系承关系v类成成员的可的可见性性§公共成公共成员::publicpublic§保保护成成员::protectedprotected§私有成私有成员::privateprivatev继承的方式承的方式§公有公有继承承(public)(public)§保保护继承承(protected)(protected)§私有私有继承承(private)(private)v派生派生类继承了基承了基类中的所有成中的所有成员,,但不包括但不包括§构造函数构造函数§析构函数析构函数24 8.2.3 8.2.3 访问控制和控制和继承关系承关系v不同不同继承方式决定的不同承方式决定的不同访问控制控制权限体限体现在:在:§①①派生派生类的的成成员函数函数对其其继承的基承的基类成成员的的访问控制控制;;§②②其其它它模模块通通过派派生生类对象象对其其继承承的的基基类成成员的的访问控控制。

      制private:protected:public:基类???派生类publicprotectedprivate继承方式决定继承成员的访问权限继承来的成员的访问权限?25 1. 1. 公有公有继承承 公有公有继承的派生承的派生类定定义形式:形式: class class 派生派生类名:名:publicpublic 基基类名名{ {派生派生类新成新成员定定义;;} }; ;private:protected:public:基类???派生类1.基基类成成员 在派生类中的访问属性不变2.派生派生类的成的成员函数函数 可以访问基类的公有成员和保护成员,不能访问基类的私有成员;3.派生派生类以外的其它函数以外的其它函数 可以通过派生类的对象,访问从基类继承的公有成员, 但不能访问从基类继承的保护成员和私有成员privateprotectedpublic派生类成员函数可以访问派生类对象基类成员的属性public26 vpublicpublic是定是定义公有公有继承方式的关承方式的关键字v公有公有继承方式定承方式定义的派生的派生类,,继承了基承了基类中中除构造函数和析除构造函数和析构函数构函数外的其余成外的其余成员:公有成:公有成员、保、保护成成员和私有成和私有成员v被被继承的基承的基类成成员在派生在派生类中仍将中仍将保持保持其其原来的原来的访问属性属性。

      v派生派生类的的成成员函数函数可以可以访问基基类的公有成的公有成员和保和保护成成员,,不不能能访问基基类的的私有成私有成员; ;v派生派生类以外的其它函数可以通以外的其它函数可以通过派生派生类的的对象,象,访问从基从基类继承的公有成承的公有成员, , 但但不能不能访问从基从基类继承的承的保保护成成员和私有和私有成成员 8.2.3 8.2.3 访问控制和控制和继承关系承关系27 class Point//基基类Point类的定的定义{public://公有函数成公有函数成员void InitP(float xx=0, float yy=0) {X=xx;Y=yy;}void Move(float xOff, float yOff) {X+=xOff;Y+=yOff;}float GetX() {return X;}float GetY() {return Y;}private://私有数据成私有数据成员float X,Y;};8.2.3 8.2.3 访问控制和控制和继承关系承关系28 class Rectangle: public Point//派生派生类声明部分声明部分{public://新增公有函数成新增公有函数成员void InitR(float x, float y, float w, float h){ InitP(x,y); //??访问基基类公有成公有成员函数函数 W=w;H=h;}float GetH() {return H;}float GetW() {return W;}private://新增私有数据成新增私有数据成员float W,H;};l派生派生类中的中的 成成员函函数数 可以直接可以直接访问基基类中的中的publicpublic和和protectedprotected成成员,但不,但不能能访问基基类的的privateprivate成成员。

      8.2.3 8.2.3 访问控制和控制和继承关系承关系29 main(){ Rectangle rect; cout<

      8.2.3 8.2.3 访问控制和控制和继承关系承关系错误31 class Point//基基类Point类的定的定义{public:void InitP(float xx=0, float yy=0) {X=xx;Y=yy;}void Move(float xOff, float yOff) {X+=xOff;Y+=yOff;}float GetX() {return X;}float GetY() {return Y;}protected:float X,Y;};8.2.3 8.2.3 访问控制和控制和继承关系承关系32 class Rectangle: public Point//派生派生类声明部分声明部分{public://新增公有函数成新增公有函数成员void InitR(float x, float y, float w, float h){X=x; Y=y; //??访问基基类的保的保护成成员 W=w;H=h;}float GetH() {return H;}float GetW() {return W;}private://新增私有数据成新增私有数据成员float W,H;};l派生派生类中的中的 成成员函函数数 可以直接可以直接访问基基类中的中的public和和protected成成员,但不能,但不能访问基基类的的private成成员。

      8.2.3 8.2.3 访问控制和控制和继承关系承关系正确正确33 main(){ Rectangle rect; cout<

      privateprivateprivate派生类成员函数可以访问基类成员的属性private派生类对象35 vprivateprivate是定是定义私有私有继承方式的关承方式的关键字字v以以私有私有继承方式承方式定定义的派生的派生类,,继承了基承了基类中可以中可以继承的成承的成员:公有成:公有成员、保、保护成成员和私有成和私有成员,,这些成些成员在派生在派生类中的中的访问属性都是属性都是私有的私有的v派生派生类的成的成员函数函数可以可以访问基基类的公有成的公有成员和保和保护成成员,,不不能能访问基基类的的私有成私有成员v派生派生类以外的其它函数以外的其它函数则不能不能通通过派生派生类的的对象象访问从基从基类继承的任何成承的任何成员 8.2.3 8.2.3 访问控制和控制和继承关系承关系36 class Point { //基基类声明声明public: void InitP(float xx=0, float yy=0) {X=xx;Y=yy;} void Move(float xOff, float yOff) {X+=xOff;Y+=yOff;} float GetX() {return X;} float GetY() {return Y;}private: float X,Y;};8.2.3 8.2.3 访问控制和控制和继承关系承关系37 class Rectangle: private Point//派生派生类声明声明{public://新增外部接口新增外部接口void InitR(float x, float y, float w, float h){InitP(x,y);W=w;H=h;}//?派生?派生类访问基基类公有成公有成员void Move(float xOff, float yOff) {Point::Move(xOff,yOff);}float GetX() {return Point::GetX();}float GetY() {return Point::GetY();}float GetH() {return H;}float GetW() {return W;}private://新增私有数据新增私有数据float W,H;};派生派生类中的中的 成成员函数函数 可以直接可以直接访问基基类中中的的publicpublic和和protectedprotected成成员,但,但不能不能访问基基类的的privateprivate成成员。

      8.2.3 8.2.3 访问控制和控制和继承关系承关系正确正确38 class Rectangle: private Point//派生派生类声明声明{public://新增外部接口新增外部接口void InitR(float x, float y, float w, float h) { X=x; Y=y;//? W=w;H=h; }void Move(float xOff, float yOff) {Point::Move(xOff,yOff);}float GetX() {return Point::GetX();}float GetY() {return Point::GetY();}float GetH() {return H;}float GetW() {return W;}private://新增私有数据新增私有数据float W,H;};派生派生类中的中的 成成员函数函数 可以直接可以直接访问基基类中的中的publicpublic和和protectedprotected成成员,,但不能但不能访问基基类的的privateprivate成成员。

      8.2.3 8.2.3 访问控制和控制和继承关系承关系错误39 class Point{//基基类声明声明public: void InitP(float xx=0, float yy=0) {X=xx;Y=yy;} void Move(float xOff, float yOff) {X+=xOff;Y+=yOff;} float GetX() {return X;} float GetY() {return Y;}protected: float X,Y;};8.2.3 8.2.3 访问控制和控制和继承关系承关系40 class Rectangle: private Point//派生派生类声明声明{public://新增外部接口新增外部接口void InitR(float x, float y, float w, float h) { X=x; Y=y;//?? W=w;H=h; }void Move(float xOff, float yOff) {Point::Move(xOff,yOff);}float GetX() {return Point::GetX();}float GetY() {return Point::GetY();}float GetH() {return H;}float GetW() {return W;}private://新增私有数据新增私有数据float W,H;};8.2.3 8.2.3 访问控制和控制和继承关系承关系正确正确41 main(){ Rectangle rect; cout<

      8.2.3 8.2.3 访问控制和控制和继承关系承关系错误错误42 3. 3. 保保护继承承 保保护继承的派生承的派生类定定义形式:形式: class class 派生派生类名:名:protectedprotected 基基类名名{ {派生派生类新成新成员定定义;;} }; ;private:protected:public:基类???派生类1.基基类成成员::公有成公有成员和保和保护成成员在派生在派生类中中变成保成保护类型的,基型的,基类的私的私有成有成员属性不属性不变2.派生派生类的成的成员函数函数:可以可以访问基基类的公有成的公有成员和保和保护成成员,不能,不能访问基基类的私有成的私有成员;3.派生派生类以外的其它函数以外的其它函数:不能通不能通过派生派生类的的对象,象,访问从基从基类继承的任承的任何成何成员privateprotectedprotected派生类成员函数可以访问基类成员的属性prot-ected派生类对象43 vprotectedprotected是定是定义保保护继承方式的关承方式的关键字字v以以保保护继承方式承方式定定义的派生的派生类,,继承了基承了基类中可以中可以继承的成承的成员:公有成:公有成员、保、保护成成员和私有成和私有成员。

      其中基其中基类的的公有成公有成员和保和保护成成员在派生在派生类中中访问控制属性控制属性变成成保保护类型的型的,基,基类的的私有成私有成员保持保持原来属性原来属性v派生派生类的成的成员函数函数可以可以访问基基类的公有成的公有成员和保和保护成成员,,不不能能访问基基类的的私有成私有成员v派生派生类以外的其它函数以外的其它函数则不能不能通通过派生派生类的的对象象访问从基从基类继承的承的任何成任何成员 8.2.3 8.2.3 访问控制和控制和继承关系承关系44 class Point { //基基类声明声明public: void InitP(float xx=0, float yy=0) {X=xx;Y=yy;} void Move(float xOff, float yOff) {X+=xOff;Y+=yOff;} float GetX() {return X;} float GetY() {return Y;}private: float X,Y;};8.2.3 8.2.3 访问控制和控制和继承关系承关系45 class Rectangle: protected Point//派生派生类声明声明{public://新增外部接口新增外部接口void InitR(float x, float y, float w, float h){InitP(x,y);W=w;H=h;}//?派生派生类访问基基类公有成公有成员void Move(float xOff, float yOff) {Point::Move(xOff,yOff);}float GetX() {return Point::GetX();}float GetY() {return Point::GetY();}float GetH() {return H;}float GetW() {return W;}private://新增私有数据新增私有数据float W,H;};派生派生类中的中的 成成员函数函数 可以直接可以直接访问基基类中中的的publicpublic和和protectedprotected成成员,,但不能但不能访问基基类的的privateprivate成成员。

      8.2.3 8.2.3 访问控制和控制和继承关系承关系正确正确46 class Rectangle: protected Point //派生派生类声明声明{public: //新增外部接口新增外部接口void InitR(float x, float y, float w, float h) { X=x; Y=y;//? W=w;H=h; }void Move(float xOff, float yOff) {Point::Move(xOff,yOff);}float GetX() {return Point::GetX();}float GetY() {return Point::GetY();}float GetH() {return H;}float GetW() {return W;}private: //新增私有数据新增私有数据float W,H;};派生派生类中的中的 成成员函数函数 可以直接可以直接访问基基类中的中的publicpublic和和protectedprotected成成员,,但不能但不能访问基基类的的privateprivate成成员。

      8.2.3 8.2.3 访问控制和控制和继承关系承关系错误47 class Point { //基基类声明声明public: void InitP(float xx=0, float yy=0) {X=xx;Y=yy;} void Move(float xOff, float yOff) {X+=xOff;Y+=yOff;} float GetX() {return X;} float GetY() {return Y;}protected: float X,Y;};8.2.3 8.2.3 访问控制和控制和继承关系承关系48 class Rectangle: protected Point //派生派生类声明声明{public: //新增外部接口新增外部接口void InitR(float x, float y, float w, float h) { X=x; Y=y;//?? W=w;H=h; }void Move(float xOff, float yOff) {Point::Move(xOff,yOff);}float GetX() {return Point::GetX();}float GetY() {return Point::GetY();}float GetH() {return H;}float GetW() {return W;}private: //新增私有数据新增私有数据float W,H;};派生派生类中的中的 成成员函数函数 可以直接可以直接访问基基类中的中的publicpublic和和protectedprotected成成员,,但不能但不能访问基基类的的privateprivate成成员。

      8.2.3 8.2.3 访问控制和控制和继承关系承关系正确正确49 main(){ Rectangle rect; cout<

      v在派生在派生类作用域内或者在作用域内或者在类外通外通过派生派生类的的对象直象直接使用接使用这个成个成员名,只能名,只能访问到派生到派生类中声明的同中声明的同名新成名新成员,,这个新成个新成员覆盖了从基覆盖了从基类继承的同名成承的同名成员,,这种情况称种情况称为同名覆盖同名覆盖 8.2.4 8.2.4 同名覆盖同名覆盖53 class base {public: void f () {cout<<"base"<using namespace std;class base{ public: void function(){cout<<"function of class base"<

      v同名覆盖同名覆盖55 void main(){ deriver derobj; derobj.function();}输出出结果果:function of class deriver同名覆盖示例同名覆盖示例 56 第第8 8章章 继承与派生承与派生8.1 8.1 继承的概念承的概念8.2 8.2 定定义基基类和派生和派生类8.3 8.3 构造函数和析构函数构造函数和析构函数8.4 8.4 转换与与继承承57 8.3 8.3 派生派生类构造函数和析构函数构造函数和析构函数v派派生生类继承承了了基基类中中除除构构造造函函数数和和析析构构函函数数之之外外的的所有成所有成员v基基类的构造函数和析构函数不能被派生的构造函数和析构函数不能被派生类所所继承承; ;v派生派生类一般需要定一般需要定义自己的构造函数和析构函数自己的构造函数和析构函数; ;v派生派生类的构造及析构函数通常会受到基的构造及析构函数通常会受到基类构造及析构造及析构函数的影响构函数的影响58 8.3.1 8.3.1 基基类只有只有无参数无参数的构造函数的构造函数v在基在基类具有具有无参构造函数无参构造函数,派生,派生类又又没有定没有定义构造构造函数函数的的时候,系候,系统会会自自动的的调用基用基类无参构造函数无参构造函数,,来构造派生来构造派生类对象中的基象中的基类成分。

      成分59 #includeusing namespace std;class base {private: int m_data;public: void SetData(int data){m_data=data;} int GetData(){return m_data;}};使用系使用系统提供的默提供的默认构造函数构造函数60 class deriver:public base{private: int m_member;public: void SetMember(int m){ m_member=m;} int GetMember(){return m_member;}};使用系使用系统提供的默提供的默认构造函数构造函数61 void main(){ int n(10); deriver obj; obj.SetMember(n); cout<

      63 v如果基如果基类和和对象数据成象数据成员的的构造函数都无参数构造函数都无参数,,派生派生类构造函数构造函数形参表中将形参表中将只包含只包含用于初始化它用于初始化它自己的自己的基本基本类型数据成型数据成员的参数的参数v如果如果这个个派生派生类恰好恰好没有没有基本基本类型的数据成型的数据成员,,则其构造函数的形参表其构造函数的形参表为空,空,可以不定可以不定义构造函构造函数,而使用系数,而使用系统提供的默提供的默认构造函数构造函数 8.3.1 8.3.1 基基类只有无参数的构造函数只有无参数的构造函数64 8 8.3.3.2 .2 派生派生类的构造函数的构造函数v不参与不参与继承的特殊函数承的特殊函数§构造函数构造函数§析构函数析构函数§作作为特特权地位的友元函数地位的友元函数§赋值运算符函数运算符函数v派生派生类需要自己定需要自己定义的构造函数和析构函数的构造函数和析构函数65 v基基类的构造函数不被的构造函数不被继承,需要在派生承,需要在派生类中自行定中自行定义 v派生派生类的构造函数完成:的构造函数完成:§初始化本初始化本类的数据成的数据成员;;§完成派生完成派生类中基中基类成分的初始化:通成分的初始化:通过调用基用基类的构造的构造函数,并函数,并为基基类的构造函数的构造函数传递参数;参数;§如果数据成如果数据成员有有对象,象,则需需调用用对象成象成员的构造函数;的构造函数;8 8.3.3.2 .2 派生派生类的构造函数的构造函数66 v派生派生类的构造函数:的构造函数:§构造函数构造函数参数表参数表中以中以合适的初合适的初值为参数,初始化本参数,初始化本类中中新增成新增成员。

      §利用利用成成员初始化表初始化表隐含含调用用基基类和和新增新增对象数据成象数据成员的的构造函数,初始化它构造函数,初始化它们各自的数据成各自的数据成员v构造函数的构造函数的调用次序用次序§系系统会使用会使用派生派生类构造函数的形参表的参数构造函数的形参表的参数调用用基基类和和内嵌内嵌对象成象成员的构造函数的构造函数 8 8.3.3.2 .2 派生派生类的构造函数的构造函数67 v派生派生类构造函数的一般形式构造函数的一般形式: : 派派生生类名名::::派派生生类名名( (基基类所所需需的的形形参参,,本本类成成员所所需的形参需的形参) ): :基基类1(1(基基类参数表参数表1), …,1), …,基基类n(n(基基类参数表参数表n),n),对象象成成员1(1(对象象参参数数表表1), 1), …,…,对象象成成员m(m(对象象参参数数表表m)m){ { 本本类基本基本类型数据成型数据成员初始化;初始化;} } 8.3.2 8.3.2 派生派生类构造函数构造函数初始化列表68 v单继承承时的构造函数的构造函数 派生派生类名名::::派生派生类名名( (基基类所需的形参,本所需的形参,本类成成员所需的形参所需的形参) ): :基基类名名( (参数参数) ){ { 本本类成成员初始化初始化赋值语句;句; } } 8.3.2 8.3.2 派生派生类构造函数构造函数69 例例8-4 8-4 单继承派生承派生类构造函数构造函数70 v多文件多文件结构:构:§主函数:主函数:ch8_4_main().cppch8_4_main().cpp§类TShapeTShape的声明:的声明:§类TShapeTShape的的实现::§类TEllipseTEllipse的声明:的声明:§类TEllipseTEllipse的的实现::例例8-4 8-4 单继承派生承派生类构造函数构造函数71 #include "TShape04.h"#include "TShape04.h"#include #include TShape::TShape(uint x, uint y)TShape::TShape(uint x, uint y){ { _x = x; _x = x; _y = y; _y = y;} }void TShape::Draw()void TShape::Draw(){ { std::cout<<"This is TShape::Draw()"<

      允色允许TShapeTShape的派生的派生类直接直接访问这些些颜色属性,而不允色属性,而不允许在在类外外通通过类的的对象直接象直接访问这些属性些属性 * */ / uchar _RED, _GREEN, _BLUE; uchar _RED, _GREEN, _BLUE;public:public: TShape(uint x, uint y);TShape(uint x, uint y); void getXY(uint& x, uint& y); void getXY(uint& x, uint& y); void setXY(uint x, uint y); void setXY(uint x, uint y); void Draw(); void Draw(); void getRGB(uchar& R, uchar& G, void getRGB(uchar& R, uchar& G, uchar& B);uchar& B); void setRGB(uchar R, uchar G, uchar void setRGB(uchar R, uchar G, uchar B);B);};};例例8-4 8-4 单继承派生承派生类构造函数构造函数72 #include "TEllipse04.h"#include "TEllipse04.h"#include #include TEllipse::TEllipse(uint longR, uint shortR, TEllipse::TEllipse(uint longR, uint shortR, uint x, uint y):TShape(x,y){ uint x, uint y):TShape(x,y){ _longR = longR; _longR = longR; _shortR = shortR; _shortR = shortR; // //在派生在派生类构造函数中初始化基构造函数中初始化基类保保护成成员 _RED = 0x00; _RED = 0x00; _GREEN = 0x00; _GREEN = 0x00; _BLUE = 0x00; _BLUE = 0x00; } }TEllipse::~TEllipse(){TEllipse::~TEllipse(){} }void TEllipse::Draw(){void TEllipse::Draw(){ uint x, y; uint x, y; getXY(x, y); // getXY(x, y); //调用基用基类函数函数获取取椭圆的的圆心坐心坐标 std::cout<<"Draw an ellipse with color("; std::cout<<"Draw an ellipse with color("; std::cout<(_RED) <<"," std::cout<(_RED) <<"," <(_GREEN)<<"," <(_GREEN)<<"," <(_BLUE) <<") at <(_BLUE) <<") at point(";point(";// std::cout<<_x<<","<<_y<<")"<#includeusing namespace std;using namespace std;void main()void main(){ { TEllipse elps(10u,5u,20u,30u);TEllipse elps(10u,5u,20u,30u); elps.setRGB(0x00,0x00,0xff elps.setRGB(0x00,0x00,0xff);//);//调用基用基类的函数的函数访问基基类的保的保护成成员 // // elps._RED=0x10elps._RED=0x10; ; // // 错误,不能通,不能通过派生派生类的的对象象调用基用基类的私有成的私有成员 elps.Draw(); elps.Draw(); ////调用派生用派生类的的DrawDraw函数函数 } }例例8-4 8-4 单继承派生承派生类构造函数构造函数74 派生派生类名名::::派生派生类名名 ( (基基类所需形参,本所需形参,本类成成员所需形参所需形参) ) : :基基类1(1(基基类参数表参数表1), 1), ……, ,基基类n(n(基基类参数表参数表n),n),对象成象成员1(1(对象参数表象参数表1), 1), ……, ,对象成象成员m(m(对象参数表象参数表m)m){ { 本本类基本基本类型数据成型数据成员初始化;初始化;} } 初始化列表包含包含内嵌内嵌对象象的派生的派生类构造函数构造函数75 v派生派生类的构造函数提供:的构造函数提供:§基基类构造函数形参表所需的参数构造函数形参表所需的参数§初始化派生初始化派生类的内嵌的内嵌对象数据成象数据成员所需的参数所需的参数§初始化派生初始化派生类基本数据基本数据类型成型成员所需的参数所需的参数v将例将例8-48-4中的中的颜色抽取形成一个新色抽取形成一个新类TColorTColor,用,用TColorTColor类的的对象象作作为TShapeTShape类中的数据中的数据成成员,重,重新新设计程序。

      程序包含包含内嵌内嵌对象象的派生的派生类构造函数构造函数76 例例8-5 8-5 派生派生类的构造函数的构造函数77 v多文件多文件结构:构:§主函数:主函数:ch8_5_main().cppch8_5_main().cpp§类TColorTColor的声明:的声明:§类TColorTColor的的实现:: §类TShapeTShape的声明:的声明:§类TShapeTShape的的实现::§类TEllipseTEllipse的声明:的声明:§类TEllipseTEllipse的的实现::§头文件文件例例8-5 8-5 派生派生类的构造函数的构造函数78 #pragma once#pragma once#include "GlobalType05.h"#include "GlobalType05.h"#include "TColor05.h"#include "TColor05.h"class TShapeclass TShape{ {private:private: uint _x, _y; // uint _x, _y; //几何形状的位置几何形状的位置protected:protected: TColor _color; // TColor _color; //颜色色public:public: TShape(uint x, uint y);TShape(uint x, uint y); TShape(uint x, uint y, TColor color); TShape(uint x, uint y, TColor color); ~TShape(); ~TShape(); void getXY(uint& x, uint& y) const; void getXY(uint& x, uint& y) const; void setXY(uint x, uint y); void setXY(uint x, uint y); void Draw(); void Draw(); TColor getColor() const; TColor getColor() const; void setColor(TColor color); void setColor(TColor color);};};#pragma once //#pragma once //预处理指令,避免重复包含本理指令,避免重复包含本头文件文件typedef unsigned int uint;typedef unsigned int uint;typedef unsigned char uchar;typedef unsigned char uchar;  #pragma once#pragma once#include "GlobalType05.h"#include "GlobalType05.h"enum EColorComponent {RED, GREEN, BLUE};enum EColorComponent {RED, GREEN, BLUE};class TColorclass TColor{ {private:private: uchar _RED, _GREEN, _BLUE; uchar _RED, _GREEN, _BLUE;public:public: TColor(const uchar R=0x00, const uchar TColor(const uchar R=0x00, const uchar G=0x00, G=0x00, const uchar B=0x00); const uchar B=0x00);////普通构造函数普通构造函数 TColor(const TColor& color); TColor(const TColor& color); ////拷拷贝构造函数构造函数 TColor& operator =(const TColor& color); TColor& operator =(const TColor& color);////重重载赋值运算符运算符 void setColor(uchar R, uchar G, uchar B); void setColor(uchar R, uchar G, uchar B); uchar getComponent(EColorComponent uchar getComponent(EColorComponent component) const;component) const;};};例例8-5 8-5 派生派生类的构造函数的构造函数79 #include "TColor05.h"#include "TColor05.h"TColor::TColor(uchar R/* =0x00 */, TColor::TColor(uchar R/* =0x00 */, ////普通构造函数普通构造函数 uchar G/* =0x00 */, uchar G/* =0x00 */, uchar B/* =0x00 */){ uchar B/* =0x00 */){ _RED = R; _GREEN = G; _BLUE = B; _RED = R; _GREEN = G; _BLUE = B;} }TColor::TColor(const TColor& color){TColor::TColor(const TColor& color){////拷拷贝构构造函数造函数 _RED = color._RED; _RED = color._RED; _GREEN = color._GREEN; _GREEN = color._GREEN; _BLUE = color._BLUE; _BLUE = color._BLUE;} }void TColor::setColor(uchar R, uchar G, uchar B){void TColor::setColor(uchar R, uchar G, uchar B){ _RED = R; _GREEN = G; _BLUE = B; _RED = R; _GREEN = G; _BLUE = B;} }} }#pragma once#pragma once#include "TShape05.h"#include "TShape05.h"#include "GlobalType05.h"#include "GlobalType05.h"class TEllipse: public TShapeclass TEllipse: public TShape { {protected:protected: uint _longR, _shortR; uint _longR, _shortR;public:public: TEllipse(uint longR, uint TEllipse(uint longR, uint shortR, uint x, uint y, TColor shortR, uint x, uint y, TColor color);color); TEllipse(uint longR, uint TEllipse(uint longR, uint shortR, uint x, uint y);shortR, uint x, uint y); ~TEllipse(); ~TEllipse(); void Draw(); void Draw(); void getR(uint& longR, uint& void getR(uint& longR, uint& shortR) const;shortR) const; void setR(uint longR, uint void setR(uint longR, uint shortR);shortR);};};例例8-5 8-5 派生派生类的构造函数的构造函数80 void TShape::getXY(uint& x, uint& y) void TShape::getXY(uint& x, uint& y) const{const{ x = _x; x = _x; y = _y; y = _y;} }void TShape::setXY(uint x, uint y){void TShape::setXY(uint x, uint y){ _x = x; _x = x; _y = y; _y = y;} }TColor TShape::getColor() constTColor TShape::getColor() const{ {return _color;return _color;} }void TShape::setColor(TColor color)void TShape::setColor(TColor color){ { _color=color; _color=color;} }#include "TShape05.h"#include "TShape05.h"#include "TColor05.h"#include "TColor05.h"#include #include TShape::TShape(uint x, uint y):_color(){TShape::TShape(uint x, uint y):_color(){ _x = x; _x = x; _y = y; _y = y;} }TShape::TShape(uint x, uint y,TColor color){TShape::TShape(uint x, uint y,TColor color){ _x = x; _x = x; _y = y; _y = y;_color=color;_color=color;} }void TShape::Draw(){void TShape::Draw(){ uint R,G,B; uint R,G,B;R=static_cast(_color.getComponent(RED));R=static_cast(_color.getComponent(RED));G=static_cast(_color.getComponent(GREEN)G=static_cast(_color.getComponent(GREEN)););B=static_cast(_color.getComponent(BLUE))B=static_cast(_color.getComponent(BLUE)); ; std::cout<<"Draw an shape with color("; std::cout<<"Draw an shape with color("; std::cout<#include TEllipse::TEllipse(uint longR, uint shortR, TEllipse::TEllipse(uint longR, uint shortR, uint x, uint y,TColor color):TShape(x,y){ uint x, uint y,TColor color):TShape(x,y){ _longR = longR; _longR = longR; _shortR = shortR; _shortR = shortR; _color=color; _color=color; } }TEllipse::TEllipse(uint longR, uint shortR, TEllipse::TEllipse(uint longR, uint shortR, uint x, uint y):TShape(x,y){ uint x, uint y):TShape(x,y){ _longR = longR; _longR = longR; _shortR = shortR; _shortR = shortR;} }TEllipse::~TEllipse(){TEllipse::~TEllipse(){} }void TEllipse::Draw(){void TEllipse::Draw(){ uint x, y; uint x, y; getXY(x, y); // getXY(x, y); //调调用基用基类类函数函数获获取取椭圆椭圆的的圆圆心坐心坐标标uint R,G,B;uint R,G,B;R=static_cast(_color.getComponent(RED));R=static_cast(_color.getComponent(RED));G=static_cast(_color.getComponent(GREEN));G=static_cast(_color.getComponent(GREEN));B=static_cast(_color.getComponent(BLUE));B=static_cast(_color.getComponent(BLUE)); std::cout<<"Draw an ellipse with color("; std::cout<<"Draw an ellipse with color("; std::cout<#includeusing namespace std;using namespace std;void main()void main(){ { TShape shp(0u,0u); TShape shp(0u,0u);shp.setColor(TColor(0xff,0x00,0x00));shp.setColor(TColor(0xff,0x00,0x00));cout<<__FILE__<<":"<<__LINE__<<" ";cout<<__FILE__<<":"<<__LINE__<<" ";shp.Draw();shp.Draw();TEllipse elps01(10u,5u,0u,0u);TEllipse elps01(10u,5u,0u,0u);cout<<__FILE__<<":"<<__LINE__<<" ";cout<<__FILE__<<":"<<__LINE__<<" ";elps01.Draw();elps01.Draw(); 例例8-5 8-5 派生派生类的构造函数的构造函数 TEllipse TEllipse elps02(10u,5u,20u,30u,TColor(0x00,0xff,0x00));elps02(10u,5u,20u,30u,TColor(0x00,0xff,0x00));cout<<__FILE__<<":"<<__LINE__<<" ";cout<<__FILE__<<":"<<__LINE__<<" ";elps02.TShape::Draw();elps02.TShape::Draw();cout<<__FILE__<<":"<<__LINE__<<" ";cout<<__FILE__<<":"<<__LINE__<<" ";elps02.Draw();elps02.Draw();elps02.setColor(shp.getColor());elps02.setColor(shp.getColor());cout<<__FILE__<<":"<<__LINE__<<" ";cout<<__FILE__<<":"<<__LINE__<<" ";elps02.Draw();elps02.Draw(); elps02.setColor(TColor(shp.getColor()));elps02.setColor(TColor(shp.getColor()));cout<<__FILE__<<":"<<__LINE__<<" ";cout<<__FILE__<<":"<<__LINE__<<" ";elps02.Draw();elps02.Draw(); } }83 #pragma once#pragma once#include "GlobalType06.h"#include "GlobalType06.h"#include "TColor06.h"#include "TColor06.h"class TShape{class TShape{private:private: uint _x, _y; // uint _x, _y; //几何形状的位置几何形状的位置protected:protected: TColor _color; // TColor _color; //颜色色public:public:// TShape(uint x, uint y);// TShape(uint x, uint y); TShape(uint x=0u, uint y=0u);TShape(uint x=0u, uint y=0u);////默默认构构造函数造函数 TShape(uint x, uint y, TColor color); TShape(uint x, uint y, TColor color); ~TShape(); ~TShape(); void getXY(uint& x, uint& y) const; void getXY(uint& x, uint& y) const; void setXY(uint x, uint y); void setXY(uint x, uint y); void Draw(); void Draw(); TColor getColor() const; TColor getColor() const; void setColor(TColor color); void setColor(TColor color);};};#include "TEllipse06.h"#include "TEllipse06.h"#include #include TEllipse::TEllipse(uint longR, uint shortR,TEllipse::TEllipse(uint longR, uint shortR,// uint x, uint y, TColor // uint x, uint y, TColor color):TShape(x,y){color):TShape(x,y){ uint x, uint y, TColor uint x, uint y, TColor color){color){ _longR = longR; _longR = longR; _shortR = shortR; _shortR = shortR; // //在派生在派生类构造函数中构造函数中访问基基类保保护成成员 _color=color; _color=color;} }TEllipse::TEllipse(uint longR, uint shortR,TEllipse::TEllipse(uint longR, uint shortR,// uint x, uint y):TShape(x,y){// uint x, uint y):TShape(x,y){ uint x, uint y){ uint x, uint y){ _longR = longR; _longR = longR; _shortR = shortR; _shortR = shortR;} }例例8-6 8-6 遗漏的基漏的基类构造函数构造函数84 派生派生类的构造函数的一般的构造函数的一般总结v派生派生类的构造函数的的构造函数的职责1.1.初始化基初始化基类2.2.初始化初始化对象数据成象数据成员3.3.初始化基本初始化基本类型的数据成型的数据成员v方式方式1.1.构造函数初始化列表构造函数初始化列表2.2.构造函数函数体构造函数函数体§除非有特殊要求除非有特殊要求 ( (const const 或者或者 referencereference 数据成数据成员只能只能由初始化列表来由初始化列表来获得初得初值) )v若不需做上述工作,若不需做上述工作,则可不定可不定义构造函数,而使用构造函数,而使用系系统提供的默提供的默认构造函数。

      构造函数 85 派生派生类的构造函数的构造函数v构造函数的构造函数的调用次序用次序1.基基类的构造函数的构造函数2.内嵌内嵌对象的构造函数象的构造函数3.派生派生类的构造函数的构造函数v因此因此§基基类 和和 内嵌内嵌对象象 的初始化的初始化只能放在初只能放在初始化列表中始化列表中,不能放到派生,不能放到派生类的构造函数体中的构造函数体中•多继承时,基类构造函数的调用顺序: 按照定按照定义派生派生类时这些基些基类被被继承的承的顺序序, 与他们在初始化列表的次序无关•派生类的多个对象成员的构造函数的调用顺序: 按照派生按照派生类定定义这些成些成员的的顺序序进行行, 与他们在初始化列表中的先后次序无关 有多个基有多个基类?? 多个内嵌多个内嵌对象?象?86 8.3.4 8.3.4 派生派生类的析构函数的析构函数 v派生派生类不能不能继承基承基类的析构函数的析构函数,需要,需要自己定自己定义析构函数,以便在派生析构函数,以便在派生类对象消亡之前象消亡之前进行必要行必要的清理工作。

      的清理工作v派生派生类的析构函数只的析构函数只负责清理清理它它新定新定义的的非非对象象数据成数据成员,,对象数据成象数据成员由由对象成象成员所属所属类的析的析构函数构函数负责析构v析构函数的析构函数的调用次序与构造函数相反用次序与构造函数相反§先派生先派生类析构函数,再基析构函数,再基类析构函数析构函数°复习:析构函数的功能在对象消亡之前进行必要的清理工作87 class TColor{class TColor{private:private: string _color; string _color;public:public: TColor(string color="BLACK") { TColor(string color="BLACK") { cout<<"TColor cout<<"TColor构造函数构造函数"<#include #include #include using namespace std;using namespace std;class TPoint{class TPoint{protected:protected: int _x, _y; int _x, _y;public:public: TPoint(int x=0, int y=0) { TPoint(int x=0, int y=0) { cout<<"TPoint cout<<"TPoint构造函数构造函数"<<"("<using namespace std;class base{private: int m_base_data;public: base(int data){m_base_data=data; cout<<"base object construction"<

      v当派生当派生类对象消亡象消亡时,系,系统调用析构函数用析构函数的的顺序与建立派生序与建立派生类对象象时调用构造函数用构造函数的的顺序序正正好相反好相反,即先,即先调用用派生派生类的析构函数的析构函数,再,再调用用其其对象数据成象数据成员的析构函数的析构函数,最后,最后调用基用基类的的析构函数析构函数 8.3.4 8.3.4 派生派生类的析构函数的析构函数 97 第第8 8章章 继承与派生承与派生8.1 8.1 继承的概念承的概念8.2 8.2 定定义基基类和派生和派生类8.3 8.3 构造函数和析构函数构造函数和析构函数8.4 8.4 转换与与继承承98 8.4 8.4 转换与与继承承v深入了解派生深入了解派生类的成的成员的布局方式的布局方式v派生派生类对象与基象与基类对象之象之间转换的一般的一般规则99 8.4.1 8.4.1 派生派生类到基到基类的的转换v派生派生类到基到基类的的转换有以下三种情况:有以下三种情况:§派生派生类对象象转换为基基类对象;象;§基基类对象指象指针指向指向派生派生类对象;象;§用派生用派生类对象象初始化初始化基基类对象的引用象的引用100 public:public: TCircle(int mx=0, int my=0, int mr=1): TCircle(int mx=0, int my=0, int mr=1): TShape(mx, my) { r = mr; }TShape(mx, my) { r = mr; } void Show() {TShape::Show();cout<<"\tr="<(c); // s = static_cast(c); cout<<"s=c\t\t"; cout<<"s=c\t\t"; s.Show(); cout<#include using namespace std;using namespace std;class TShape {class TShape {protected:protected: int x, y; int x, y;public:public: TShape(int mx=0, int my=0) TShape(int mx=0, int my=0) { x=mx; y=my; }{ x=mx; y=my; } void Show() void Show() {cout<<"x="<(&c); //dynamic_cast(&c); //基基类对象指象指针指向派生指向派生类对象象 if(0!=ps) { if(0!=ps) { cout<<"ps=&c\t\t"; cout<<"ps=&c\t\t"; ps->Show(); cout<Show(); cout<#include using namespace std;using namespace std;class TShape {class TShape {protected:protected: int x, y; int x, y;public:public: TShape(int mx=0, int my=0) { x=mx; TShape(int mx=0, int my=0) { x=mx; y=my; }y=my; } void Show() {cout<<"x="<#include using namespace std;using namespace std;class TShape {class TShape {protected:protected: int x, y; int x, y;public:public: TShape(int mx=0, int my=0) { x=mx; TShape(int mx=0, int my=0) { x=mx; y=my; }y=my; } void Show() {cout<<"x="<点击阅读更多内容

      关于金锄头网 - 版权申诉 - 免责声明 - 诚邀英才 - 联系我们
      手机版 | 川公网安备 51140202000112号 | 经营许可证(蜀ICP备13022795号)
      ©2008-2016 by Sichuan Goldhoe Inc. All Rights Reserved.