5:18:38 第七章组合与继承 创建新类时,不必每次都从头重新做起,可以利用已经存 在的类,创建新的类 利用已经存在的类创建新类,有两种方法 组合 继承 本章主要内容 1.组合创建新类的方法 2.继承创建新类的方法 掌握 3.继承方式、访问控制 理解、掌握 4.构造函数与析构函数 掌握 5.继承成员的调整 掌握 6.多重继承、虚拟继承(虚基类继承)
15:13:38 第七章 组合与继承 ➢ 创建新类时,不必每次都从头重新做起,可以利用已经存 在的类,创建新的类 ➢ 利用已经存在的类创建新类,有两种方法 .组合 .继承 本章主要内容 1. 组合创建新类的方法 2. 继承创建新类的方法 ——掌握 3. 继承方式、访问控制 ——理解、掌握 4. 构造函数与析构函数 ——掌握 5. 继承成员的调整 ——掌握 6. 多重继承、虚拟继承(虚基类继承)
§1组合( composition) 15:13:38 新类由已经存在的类的对象组合而成,原有类的对象是新 类的成员对象 //useful.h /composition. h class X 并#inc1ude“ useful.h” int 1 class Y( public: int 1 X0{i=0;} public void set(int iii=ii Ⅹx0bj int readO const [return i; Y0 li=0; int permuted void f(int iii=ii freturn i=i*47 int go const return i void maino[ X是已经存在的类,Y是由X Y yob j; 类的对象组合而成的新类 y0bjf(47); V是外围类,x0b是Y类的公 yob j xbj set(37); 有成员对象
§ 15:13:38 1 组 合(composition) ➢ 新类由已经存在的类的对象组合而成,原有类的对象是新 类的成员对象 例:组合 //useful.h class X{ int i; public: X(){i=0;} void set(int ii){i=ii;} int read()const{return i;} int permute() {return i=i*47;} }; //composition.h #include “useful.h” class Y{ int i; public: X xObj; Y(){i=0;} void f(int ii){i=ii;} int g()const{return i;} }; void main(){ Y yObj; yObj.f(47); yObj.xObj.set(37); } ➢X是已经存在的类,Y是由X 类的对象组合而成的新类 ➢Y是外围类,xObj是Y类的公 有成员对象
成员变量(对象)一般应为 private的 15:13:38 /composition.h #inc1ude“ useful.h class yi int 1 X XOI public: Yoli=0 void f(int ini=ii int gO const return i void permute (x0bJpermute0; 1 // main. cpp #include"composition. h >X是已经存在的类,Y是由X void maino( 类的对象组合而成的新类 Y yob j: 0bj.f(47); Y是外围类,x0bj是Y类的私 yOb j: permute O 有成员对象
15:13:38 ➢成员变量(对象)一般应为private的 //composition.h #include “useful.h” class Y{ int i; X xObj; public: Y(){i=0;} void f(int ii){i=ii;} int g()const{return i;} void permute(){xObj.permute();} }; //main.cpp #include “composition.h” void main(){ Y yObj; yObj.f(47); yObj.permute(); } ➢X是已经存在的类,Y是由X 类的对象组合而成的新类 ➢Y是外围类,xObj是Y类的私 有成员对象
§2继承( Inheritance) 描述类与类之间的“ is a kind of”的关系,是C+中实现 代码重用( code reuse)的重要机制 创建新类时不必从头开始,而把新类作为现有类的扩充或 把新类作为是原有类的一种特殊情况 子类、派生类 原父类、基类、超类 有的类 继承增加)新 部分部分类 类X 类Y >类Y从类X扩充而来,则称类Y继承类X或类Y从类X派生 >类X称做类Y的基类( Base class)、父类( Parent class) 或超类( Super class) 类Y称做类X的派生类 (Derived class:相对于基类)或子 类( Child class:相对于父类或 Sub class:相对于超类)
15:13:38 §2 继承(Inheritance) ➢ 描述类与类之间的“is a kind of”的关系,是C++中实现 代码重用(code reuse)的重要机制 ➢ 创建新类时不必从头开始,而把新类作为现有类的扩充或 把新类作为是原有类的一种特殊情况 父类、基类、超类 类 X 继 承 增 加 部 分 部 分 子类、派生类 类 Y 原 有 的 类 新 类 ➢类Y从类X扩充而来,则称类Y继承类X或类Y从类X派生 ➢类X称做类Y的基类(Base Class)、父类(Parent class) 或超类(Super class) ➢类Y称做类X的派生类(Derived class:相对于基类)或子 类(Child class:相对于父类或Sub Class:相对于超类)
5:18:38 继承的语法 cass新类名:继承方式已有类的类名 ,继承方式已有类名的类名2[,…] private. 扩充的私有成员 protected: 扩充的保护成员 public: 扩充的公有成员
15:13:38 ➢继承的语法 class 新类名:继承方式 已有类的类名 [,继承方式 已有类名的类名2[,…]] { private: 扩充的私有成员 protected: 扩充的保护成员 public: 扩充的公有成员 };
例:类的继承 5:13:38 class vehicle vehicle类是基类或父类,car类 int wheels; 是派生类或子类 float weight >Car类从其基类 vehicle类中继承 float loading 了所有的成员变量和成员函数 public (构造函数与析构函数除外) vehicle(int wheels, float weight, float loading) int get_wheels o float get-weight O;void maino( float get-loading o Car car(4,1000,1000,4) cout < car passengers o class car: public vehicle < end1 int passenger-load; cout < car get_wheels O public: < car. get-weight O Car(int in-wheels, floa < car. get-loading O int peoples=4) < end1 int passengers O
例:类的继承 15:13:38 class vehicle{ int wheels; float weight; float loading; public: vehicle(int wheels,float weight,float loading); int get_wheels(); float get_weight(); float get_loading(); }; class Car:public vehicle{ int passenger_load; public: Car(int in_wheels,float in_weight,float in_loading, int peoples=4); int passengers(); }; ➢vehicle类是基类或父类,car类 是派生类或子类 ➢Car类从其基类vehicle类中继承 了所有的成员变量和成员函数 (构造函数与析构函数除外) void main(){ Car car(4,1000,1000,4); cout << car.passengers() << endl; cout << car.get_wheels() << car.get_weight() << car.get_loading() << endl; }
说明 15:13:38 >派生类继承了基类中除构造函数、析构函数和重载的“=” 运算符对应的函数以外的所有成员 在派生类中动问基类成员时,仍要受基类动问控制的限制, 派生类新添加的成员函数中不能直接访问基类的 private 成员,但可访问基类的 public成员和 protected成员 例:在派生类中访问基类成员 //A.h class af #inc1ude“A.h” int x; class B: public A void fo: public protected void funco i int y, x=0;f0;//错,基类的私有成员 void g0; y=10;g0;//正确,基类的保护成员 public z=10;h0;//正确,基类的公有成员 int void ho
15:13:38 说明 ➢派生类继承了基类中除构造函数、析构函数和重载的“=” 运算符对应的函数以外的所有成员 ➢在派生类中访问基类成员时,仍要受基类访问控制的限制, 派生类新添加的成员函数中不能直接访问基类的private 成员,但可访问基类的public成员和protected成员 例:在派生类中访问基类成员 //A.h class A{ int x; void f(); protected: int y; void g(); public: int z; void h(); }; #include “A.h” class B:public A{ public: void func(){ x=0;f(); //错,基类的私有成员 y=10;g(); //正确,基类的保护成员 z=10;h(); //正确,基类的公有成员 } };
5:18:38 说明(续) 继承方式决定了从基类继承而来的成员在派生类中的访问 控制权限,用关键字 public、 private和 protected表示 分别为公有继承、私有继承和保护继承 ★私有继承使基类的保护成员和公有成员成为派生类的 私有成员 ★保护继承使基类的保护成员和公有成员成为派生类的 保护成员 ★公有继承使基类的保护成员和公有成员仍然成为派生 类的保护成员和公有成员 C++中默认的继承方式是私有继承 一般多使用公有继承,故应重点掌握公有继承
15:13:38 说明(续) ➢ 继承方式决定了从基类继承而来的成员在派生类中的访问 控制权限,用关键字public、private和protected表示, 分别为公有继承、私有继承和保护继承 ★私有继承使基类的保护成员和公有成员成为派生类的 私有成员 ★保护继承使基类的保护成员和公有成员成为派生类的 保护成员 ★公有继承使基类的保护成员和公有成员仍然成为派生 类的保护成员和公有成员 ➢ C++中默认的继承方式是私有继承 ➢ 一般多使用公有继承,故应重点掌握公有继承
5:18:38 公有继承 基类的公有成员和保护成员成为派生类的公有成员和保护 成员 #include using namespace std class a protected int X, y, public: void get-XYo t cout>x >>y, void put-XY O cout<“x=“<<x<<“,y=<y<“n’;}
15:13:38 ➢公有继承 基类的公有成员和保护成员成为派生类的公有成员和保护 成员 #include using namespace std; class A{ protected: int x,y; public: void get_XY(){ cout > x >> y; } void put_XY() { cout << “x=“ << x << “,y=“ << y << ‘\n’;} };
例:公有继承(续) 15:13:38 class b: public Al protected int s: public int get-so return s; void make-S0{s=x*y;}//x、y都是为B的保护成员 class C: public Bi protected: int h.v. public: void get-H0{out>h;} int get-vo return v; void make-vo i make-S0;∥/s=x*y;//、x、y都是C的保护成员 v=get_S0*h;//v=x*y*h
15:13:38 例:公有继承(续) class B:public A{ protected: int s; public: int get_S(){return s;} void make_S(){s=x*y;} //x、y都是为B的保护成员 }; class C:public B{ protected: int h,v; public: void get_H(){cout > h;} int get_V(){return v;} void make_V(){ make_S(); //s=x*y; //s、x、y都是C的保护成员 v=get_S()*h; //v=x*y*h; } };