您好,欢迎访问三七文档
《C++程序设计》复旦大学计算机科学技术学院张向东第三讲继承继承关系基类父类派生类子类单继承class派生类名:[继承方式]基类名{....//新成员或重定义};继承方式:publicprotectedprivate(默认)派生类包含基类所有成员(除了基类的构造函数和operator=)classA//基类{intx,y;public:voidf();voidg();};classB:publicA//派生类{intz;public:voidh();};定义派生类之前要有基类定义classA;//声明classB:publicA//Error{intz;public:voidh(){g();}//Error,编译程序不知道基类中是否有函数g};......B,b;//Error,编译无法确定b所需内存空间的大小派生类不能直接访问基类私有成员classA{intx;public:voidf(){...x...}};classB:publicA{public:voidh(){...x...//Error,x为基类的私有成员f();//OK,通过基类公开的函数f}};为了让派生类能够访问,基类将成员定义为公共会破坏封装,失去信息隐藏的意义classA{public:intx,y;//它们本来应该是private,但为了在......};classB:publicA//B属于A的一类用户{......voidh(){...x...//OK...Y...//OK}};voidf()//f属于A的另一类用户{Aa;...a.x...//OK,但是去了对a的数据保护...a.y...//OK,但是去了对a的数据保护为了让派生类能够访问,基类将成员定义为保护派生类可以访问,但在类外(像实例用户)依然不能访问classA{protected:intx,y;public:voidf();};classB:publicA{......voidh(){...x...//OK...y...//OKf();//OK}};voidf(){Aa;...a.x...//Error...a.y...//Errora.f();//OK}重载、覆盖、隐藏派生类如果有和基类同名的成员,基类成员被隐藏若要访问,需要基类名::成员哪怕同名函数参数并不同,基类成员也被隐藏重载、覆盖、隐藏用::访问隐藏的成员classA{intx,y;pubic:voidf();voidg(){...x...}};classB:publicA{intz;public:voidf();voidh(){f();//B类中的fA::f();//A类中的f}};......Bb;b.f();//B类中的fb.A::F();//A类中的f隐藏vs.重载classB:publicA{intz;public:voidf(int);voidh(){f(1);//OKf();//ErrorA::f();//OK}};......Bb;b.f(1);//OKb.f();//Errorb.A::f();//OKpublic继承protected继承private继承基类的public成员成为派生类的public成员成为派生类的protected成员成为派生类的private成员基类的protected成员成为派生类的protected成员成为派生类的protected成员成为派生类的private成员基类的private成员不可访问不可访问不可访问继承方式继承受限的例子classA{public:voidf();protected:voidg();private:voidh();};classB:protectedA{public:voidq();};classC:publicB{public:voidr(){q();//OKf();//OKg();//OKh();//Error,h是B的不可直接访问的成员}};......Bb;b.q();//OKb.f();//Error,f是B的protected成员b.g();//Error,g是B的protected成员b.h();//Error,h是B的不可直接访问的成员继承方式的调整classA{public:voidf1();voidf2();voidf3();protected:voidg1();voidg2();voidg3();};classB:privateA{public:A::f1;//把f1调整为publicA::g1;//把g1调整为public。是否允许弱化基类的访问控制要视具体的实现而定protected:A::f2;//把f2调整为protectedA::g2;//把g2调整为protected......};继承方式的调整classC:privateB{public:void:h(){f1();f2();g1();g2();//OKf3();g3();//Error}};Bb;......b.f1();b.g1();//OKb.f2();b.g2();b.f3();b.g3();//Error派生类对象的初始化先调用基类的构造函数如果不是基类的默认构造函数,需要在基类/成员初始化表里指明再调用成员对象的构造函数最后是派生类自己的构造函数classA{intx;public:A(){x=0;}A(inti){x=i;}};classB:publicA{inty;public:B()//将调用A的默认构造函数A(){y=0;}B(inti)//将调用A的默认构造函数A(){y=i;}B(inti,intj):A(i)//将调用A的构造函数A(inti){y=j;}};......Bb1;//调用A::A()和B::B(),b1.x等于0,b1.y等于0Bb2(1);//调用A::A()和B::B(int),b2.x等于0,b2.y等于1Bb3(1,2);//调用A::A(int)和B::B(int,int),b3.x等于1,b3.y等于2派生类的隐式拷贝构造函数,会调用基类的拷贝构造函数派生类的自定义拷贝构造函数,会调用基类的默认构造函数(除非使用基类/成员初始化表)classA{inta;public:A(){a=0;}A(constA&x){a=x.a;}......};classB:publicA{public:B(){......}......//其中没有定义拷贝构造函数};classC:publicA{public:C(){......}C(constC&)//这里将会去调用A的默认构造函数{......}......};classD:publicA{public:D(){......}D(constD&d):A(d)//这里将把d转换成A类对象,然后去掉用A的拷贝构造函数{......}......};Bb1;//将调用A()对b1.a初始化Bb2(b1);//将调用A(constA&)用b1.a对b2.a初始化(调用A的拷贝构造函数)Cc1;//将调用A()对c1.a初始化Cc2(c1);//将调用A()对c2.a初始化(注意:调用A的默认构造函数,不是A的拷贝构造函数)Dd1;//将调用A()对d1.a初始化Dd2(d1);//将调用A(constA&)用d1.a对d2.a初始化(调用A的拷贝构造函数)派生类不继承赋值操作如未定义,则从基类继承的成员按基类operator=进行,自己的成员逐个赋值classA{......};classB:publicA{......public:B&operator=(constB&b){if(&b==this)return*this;//防止自身赋值*(A*)this=b;//调用基类的赋值操作符对基类成员进行赋值......return*this;}};this-A::operator=(b);单继承实例classEmployee//普通职员类{Stringname;//String为例7-7种定义的字符串类intsalary;public:Employee(constchar*s,intn=0):name(s){salary=n;}voidset_salary(intn){salary=n;}intget_salary()const{returnsalary;}Stringget_name()const{returnname;}};constintMAX_NUM_OF_EMPS=20;classManager:publicEmployee//部门经理类{Employee*group[MAX_NUM_OF_EMPS]//被管理的职员对象(指针)数组intnum_of_emps;//被管理的职员人数public:Manager(constchar*s,intn=0):Employee(s,n){num_of_emps=0;}Employee*add_employee(Employee*e)//增加一个被管理的职员{if(num_of_emps=MAX_NUM_OF_EMPS)returnNULL;group[num_of_emps]=e;num_of_emps++;returne;}Employee*remove_employee(Employee*e)//删除一个被管理的职员{inti;for(i=0;inum_of_emps;i++)if(e-get_name()==group[i]-〉get_name())break;if(inum_of_emps){for(intj=i+1;jnum_of_emps;j++)group[j-1]=group[j];num_of_emps--;returne;}elsereturnNULL;}};......Employeee1(“JACK”,1000),e2(“Jane”,2000);Managerm(“Mark”,4000);m.add_employee(&e1);m.add_employee(&e2);coutm.get_salary()end1;继承关系(一般-特殊)聚集关系(部分-整体)private继承,它纯粹是为了代码复用classLinearList{......public:boo1insert(intx,intpos);//在线性表中位置pos后面增加元素,//当pos为0时,在表头增加元素//返回值表示操作成功或失败boolremove(int&x,intpos);//删除线性表中位置pos处的元素,//返回值表示操作成功或失败intelement(intpos)const;//返回位置pos处的元素intsearch(intx)const;//查找值为x的元素,返回元素位置,未找到返回0intlength()const;//返回元素个数};classQueue:privateLinearList//这里的继承方式private可以省略{public:boolen_queue(intx)//元素进队{returninsert(x,length());}boolde_queue(int&x)//元素出队{returnremove(x,1);}};聚集来实现纯代码复用classQueue{LinearListlist;public:boolen_queue(inti){returnlist.insert(i,list.length());}boolde_queue(int&i){returnlist.remove(i,1);}};继承常常可以用聚集来实现classA{......public:voidf();voidg();};classB:publicA{......public:voidh();......};可以采用聚集来实现:
本文标题:C++第三讲.
链接地址:https://www.777doc.com/doc-2901792 .html