560 likes | 766 Views
1. 第四章 派生类与继承. 2. 继承. 昆 虫. 派生. 有 翅 类. 无 翅 类. 蛾. 蝴蝶. 苍蝇. 单一继承. 窗 口. 滚 动 条. 可滚动的窗口. 多重继承. 4.1 派生类的概念. 4.1.1 为什么要使用继承 从现有类出发建立新的类,使新类继承老类的特点和功能,并且又加上自己的特点和功能的程序设计方法,是面向对象程序设计一个重要的技术。 老的类叫 基类 ,新的类叫 派生类 。 对派生类可做如下几种变化: (1) 可以增加新的成员数据。 (2) 可以增加新的成员函数。
E N D
1 第四章 派生类与继承
2 继承 昆 虫 派生 有 翅 类 无 翅 类 蛾 蝴蝶 苍蝇 单一继承 窗 口 滚 动 条 可滚动的窗口 多重继承 4.1 派生类的概念 4.1.1 为什么要使用继承 从现有类出发建立新的类,使新类继承老类的特点和功能,并且又加上自己的特点和功能的程序设计方法,是面向对象程序设计一个重要的技术。 老的类叫基类,新的类叫派生类。 对派生类可做如下几种变化: (1) 可以增加新的成员数据。 (2) 可以增加新的成员函数。 (3) 可以重新定义己有的成员函数。 (4) 可以改变现有成员的属性。 C++中有两种继承: 单一继承和多重继承。 对于单一继承 派生类只能有一个基类; 对于多重继承 派生类可以有多个基类。
3 class employee{ private: char name[10]; int age; char sex; char department[20]; float salary; public: void print(); }; 4.1.1为什么要使用继承? class person{ private: char name[10]; int age; char sex; public: void print(); }; 比较二个类
4 声明派生类: class 派生类名 : 派生方式 基类名 { //派生类新增的数据成员和函数成员 }; 4.1.2 派生类的声明 基类: class 类名 { 类的内容 }; 派生方式可为公有派生(用public)和私有派生(用private或缺省)。 class person{ private: char name[10]; int age; char sex; public: void print(); }; class employee : public person { private: char department[20]; float salary; public: void print(); };
5 1. 私有派生 void main() { derived obj; obj.setxy(10,20); obj.showxy(); } (1) 私有派生类对基类成员的访问 基类的公有成员相当于派生类的私有成员,派生类的成员数可以访问它。但基类的私有成员派生类的成员函数不可以访问它。 例4.1 #include <iostream.h> class base{ //定义基类 int x; public: void setx(int n) { x=n; } void showx() { cout << x << endl; } }; class derived : private base { //定义私有派生类 int y; public: void setxy(int n, int m) { setx(n); y=m; } void showxy() { cout << x << y << endl; } // 非法 不能访问 x ,改为 showx() };
6 (2) 外部函数(main)对私有派生类继承来的成员的访问 void main() { derived obj; obj.setx(10); //出错 obj.sety(20); //合法 obj.showx(); //出错 obj.showy(); //合法 } 私有派生时,基类的所有成员在派生类中都成为私有成员,外部函数不能访问。 例4.2 #include <iostream.h> class base{ //定义基类 int x; public: void setx(int n) { x=n; } void showx() { cout << x << endl; } }; class derived : private base { //定义私有派生类 int y; public: void sety(int n) { y=n; } void showy() { cout << y << endl; } };
7 2. 公有派生 在公有派生中,基类的私有成员对派生类来说仍是基类的私有成员,只能通过基类的公有成员函数访问(相当于可访问性保持不变),不允许外部函数和派生类的成员函数直接访问。基类中的公有成员相当于派生类的公有成员,外部函数和派生类的成员函数可直接访问。 例4.3 #include <iostream.h> class base{ //定义基类 int x; public: void setx(int n) { x=n; } void showx() { cout << x << endl; } }; class derived : public base {//定义公有派生类 int y; public: void sety(int n) { y=n; } void showy() { cout << y << endl; } }; void main() { derived obj; obj.setx(10); //合法 obj.sety(20); //合法 obj.showx(); //合法 obj.showy(); //合法 }
8 在作类派生时,可能导致几个类使用同一函数名或变量名,这就会产生二义性。 #include <iostream.h> void main( ) { X a; Y b; int i=a.f(); int j=b.f(); cout << "i=" << i << endl; cout << "j=" << j << endl; } 如 class X { public: int f(); }; class Y : public X { public: int f(); int g(); }; 这里 b.f() 用的是 Y 类的 f() 还是 X 类的 f()? 用的是 Y 类的 f(),编译器会自动从继承底向上搜索,这叫作支配规则。如果一定要用 X 类的 f(),则可写成 b.X::f(); X::叫作用域分辨符。
9 表4.1公有派生和私有派生的访问特性
10 4.1.3 基类的保护成员作用 无论私有派生还是公有派生,派生类无权访问它的基类的私有成员。派生类要想访问它的基类的私有成员,只能通过调用基类的成员函数的方式实现,对这有时会带来不便。C++还提供一种访问属性 protected 保护性成员。基类的保护成员具有私有成员和公有成员双重角色:对自已的对象而言它是私有成员,即不能被其他程序或函数访问(只能被类中的成员函数访问);而对派生类而言,它又相当于是基类的公有成员。当公有派生时,基类的保护成员在派生类也为保护成员。当私有派生时,相当于派生类的私有成员,派生类的成员函数可以访问它。
例4.4 保护成员的例子 #include <iostream.h> class samp{ int a; protected: int b; public: int c; samp(int n, int m ) { a=n; b=m; } //构造函数 int geta() { return a; } int getb() { return b; } }; void main () { samp obj(20,30); obj.a=88; //非法,类的私有成员不能对外 obj.b=99; //非法,类的保护成员相当于私有成员不能对外 obj.c=50 //合法,类的公有成员能对外 cout << obj.geta() << ' '; cout << obj.getb() << ' ' <<obj.c<<endl; } 11
12 例4.5 保护成员被公有派生后的例子 #include <iostream.h> class base { protected: int a,b; //保护成员 public: void setab(int n, int m) { a=n; b=m; } }; class derive:public base { int c; public: void setc(int n) { c=n; } void showabc()//a,b 相当于派生类的私有成员,成员函数可访问 { cout <<a<<' '<<b<<' '<<c<<endl; } }; void main() { derive obj; obj.setab(2,4); //基类的公有成员相当于派生类的公有成员,可被外界访问 obj.setc(3); obj.showabc(); }
13 例4.6 保护成员被私有派生后的例子 class derive1:private base { protected: int b; public: void setb(int sb) { b=sb; } }; #include <iostream.h> class base { protected: int a; //保护成员 public: void seta(int sa) { a=sa; } }; class derive2:public derive1 { int c; public: void setc(int sc) { c=sc; } void show() { cout<<"a="<<a<<endl; //非法,保护成员 a 被derive1私有派生后 成为derive1的私有成员,dervie2中不能//直接访问 cout<<“b=”<<b<<endl; //合法 cout<<“c=”<<c<<endl; } //合法 }; void main() { base op1; op1.seta(1); derive1 op2; op2.setb(2); derive2 op3; op3.setc(3); op3.show(); }
14 表4.2 基类成员在派生类中和外部函数中的访问权限
15 保护成员的这种性质还可传播给派生的派生。 例 保护成员的性质传播给派生的派生的例子。 class Base { int value; protected: void SetValue(int v) { value=v; } }; class First : public Base { int total; public: void SetTotal(int t) { total=t; SetValue(t); //使用基类的保护成员,相当于本类的保护成员 } }; class Second : public First { int count; public: void SetCount(int c) { count=c; SetValue(c); //使用基类的保护成员,相当于本类的保护成员 } };
16 4.2 派生类的构造函数和析构函数 当一个派生类有构造函数时,则它必须对自己的数据成员和继承而来的基类数据成员初始化,这和前面(第三章)讲的类定义中有对象作为数据成员类似。因此需要由派生类的构造函数调用基类的构造函数来完成。
17 4.2.1 派生类的构造函数和析构函数执行顺序 void main( ) { dervie op; } 当创建派生类对象时,首先执行基类的构造函数,随后再执行派生类的构造函数;当撤消派生类对象时,则先执行派生类的析构函数,随后再执行基类的析构函数。 例4.7 #include <iostream.h> class base { public : base( ) { cout << "执行 base 类的构造函数\n"; } ~base( ) { cout <<"执行 base 类的析构函数\n"; } }; class derive:public base { public : dervie( ):base( ) { cout << "执行 dervie 类的构造函数\n"; } ~dervie( ) { cout <<"执行 dervie 类的析构函数\n"; } };
18 4.2.2 派生类的构造函数和析构函数的定义规则 void main( ) { derive obj(30,40); obj.showi( ); obj.showj( ); } 当派生类的基类构造函数含有参数时,必须定义派生类的构造函数。格式为: 派生类的构造函数名(参数表):基类的构造函数名(参数表) { //...... } 其中,基类构造函数参数,来源于派生类的构造函数的参数表。 例4.8 #include <iostream.h> class base { int i; public: base(int n) //基类的构造函数 { cout << "执行 base 基类的构造函数\n"; i=n; } ~base( ) { cout <<"执行 base 基类的析构函数\n"; } void showi( ) { cout << i << endl; } }; class derive:public base { int j; public : dervie(int n, int m):base(m) //派生类的构造函数 { cout << "执行 dervie 派生类的构造函数\n"; j=n; } ~dervie( ) { cout <<"执行 dervie 派生类的析构函数\n"; } void showj( ) { cout << j << endl; } };
19 当派生类中还含有对象成员时,其构造函数的格式为: 派生类的构造函数名(参数表):基类的构造函数名(参数表),对象成员1(参数表),..., 对象成员n(参数表) { //...... } 定义派生类对象时构造函数执行顺序: 基类的构造函数 对象成员构造函数 派生类的构造函数; 当撤消派生类对象时,析构函数执行顺序正好相反。 例4.9#include <iostream.h> class base { int x; public: base(int i) //基类的构造函数 { cout << "执行 base 基类的构造函数\n"; x=i; } ~base() { cout <<"执行 base 基类的析构函数\n"; } void show() { cout << "x=" << x << endl; } }; class derive:public base { base d; public : dervie(int i):base(i),d(i) //派生类的构造函数 { cout << "执行 dervie 派生类的构造函数\n"; } ~dervie() { cout <<"执行 dervie 派生类的析构函数\n"; } }; void main() { derive obj(5); obj.show(); } 说明 P-105
20 4.3 多重继承 从多个类派生出一个类,也即一个类从多个基类继承称为多继承。 4.3.1 多重继承的声明 多重继承的声明格式如下: class 派生类名: 派生方式1 基类名1, ... , 派生方式n 基类名n { //派生类新增的数据成员和函数成员 }; 派生类继承了基类1 到 基类n的所有数据成员和函数成员,其访问权限规则与单继承情况一样,多继承可看成单一继承的扩展。 例4.10 #include <iostream.h> class X { int a; public: void setX(int x) { a=x; } void showX() { cout <<"a="<<a<<endl; } }; class Y { int b; public: void setY(int x) { b=x; } void showY() { cout <<"b="<<b<<endl; } };
21 class Z: public X, private Y { int c; public: void setZ(int x, int y) { c=x; setY(y); } void showZ() { showY(); cout<<"c="<<c<<endl; } // void setZ(int x, int y, int z) { a=x; setY(y); c=z; } // void showZabc() { cout<<"a="<<a<<endl; // showY(); cout<<"c="<<c<<endl; } }; void main() { Z obj; obj.setX(3); obj.showX(); obj.setY(4); //错误 obj.showY(); //错误 obj.setZ(6,8); obj.showZ(); // obj.setZ(1,2,3); // obj.showZabc(); }
22 再讲一个例 class C:public A, private B { private: int c; public: void setC(int, int); void showC( ); }; class A { private: int a; public: void setA(int); void showA( ); }; class B { private: int b; public: void setB(int); void showB( ); }; A类的公有成员(和保护成员) C类中仍是公有的(保护的) B类所有成员 C类中是私有的。
23 完整的程序如下: #include <iostream.h> class A { private: int a; public: void setA(int x){ a=x; } void showA(){ cout << a <<endl; } }; class B { private: int b; public: void setB(int x){ b=x; } void showB(){ cout << b <<endl; } };
class C:public A, private B { private: int c; public: void setC(int x, int y) { c=x; setB(y); } void showC( ) { showB( ); cout<< c <<endl; } }; 24 void main() { C obj; obj.setA(3); obj.showA(); obj.setB(5); //错误 obj.showB(); //错误 obj.setC(5,8); obj.showC(); }
25 真正生产二义性的情况是,一个派生类从多个基类派生,而这些基类又有一个相同的 基类,则在派生类访问这个共同基类的成员时会产生二义性。 class A { public: void fun() ; }; class B { public: void fun() ; void gun() ; }; class C: public A, public B { void gun() ; void hun() ; } 若有对象 C obj ; obj.fun() 是使用 A 类的 fun() 呢? 也是 B 类的 fun()? 编译器无法自动确定,因为对 C 类来说 A 类和 B 类是同一级,我们可以用成员名限定(作用域分辨操作符)来人为的消去二义性。 obj.A::fun(); obj.B::fun();
26 4.3.2 多重继承的构造函数和析构函数 设类Y从X1,X2,....Xn类派生(当只有一个X1时为单继承,否则为多继承),则派生类Y的构造函数Y的一般形式为: Y::Y(参数表0):X1(参数表1),X2(参数表2),.....,Xn(参数表n) { //… } 其调用顺序为先X1,X2,...,Xn(从左向右),最后为Y 析构函数的执行顺序和构造函数正好向反。 例4.11 #include <iostream.h> class X { int a; public: X(int sa) { a=sa; } //X类构造函数 int getX() { return a; } }; class Y { int b; public: Y(int sb) { b=sb; } //Y类构造函数 int getY() { return b; } };
class Z:public X, private Y { int c; public: Z(int sa, int sb, int sc):X(sa),Y(sb) { c=sc; } //Z类构造函数 int getZ( ) { return c; } int getY( ) { return Y::getY( ); } }; 27 void main() { Z obj(2,4,6); int ma=obj.getX(); cout << "a=" << ma << endl; int mb=obj.getY(); cout << "b=" << mb << endl; int mc=obj.getZ(); cout << "c=" << mc << endl; }
28 base base base1 base2 derived 4.3.3 虚基类 void main( ) { derived d; d.base1::b=8; d.base2::b=15; cout << "path base1==>"<<d.base1::b<<endl; cout << "path base2==>”<<d.base2::b<<endl; } 1. 为什么要引入虚基类。 一个派生类从多个基类派生,而这些基类又有一个相同的基类,则 在派生类访问这个共同基类的成员时会产生二义性。虽然我们可以 用“作用域分辨操作符”区别,但这时基类的成员有二个副本(拷贝)。 如: class base { public: int b; }; class base1:public base { }; class base2:public base { }; class derived :public base1, public base2 { public: int fun() { } }; 程序运行结果是 path base1==>8 path base2==>15 base 类中的成员 b 有二个副本,一个放 8,一个放 15。
29 2. 虚基类的概念 void main( ) { derived d; d.base1::b=8; d.base2::b=15; cout << "path base1==>”<<d.base1::b<<endl; cout << "path base2==>”<<d.base2::b<<endl; } 如果希望基类只有一个拷贝,则在定义时把基类说明成虚基类,加上virtual: class base { public: int b; }; class base1:virtual public base { }; class base2:virtual public base { }; class derived :public base1, public base2 { public: int fun() { } }; 这时程序运行结果是 path base1==>15 path base2==>15 这时也没有了二义性,可以写成 int i=d.b;
30 例4.12 void main( ) { derived obj; } #include <iostream.h> class base{ protected: int a; public: base ( ) { a=5; } }; class base1:public base { public: base1( ) { cout <<"base1 a="<<a<<endl; } }; class base2:public base { public: base2( ) { cout <<"base2 a="<<a<<endl; } }; class deeived : public base1, public base2 { public: derived( ) { cout <<"derived a="<<a<<endl; } };
31 例4.13 void main() { derived obj; } #include <iostream.h> class base{ protected: int a; public: base() { a=5; } }; class base1:virtual public base { public: base1() { cout <<"base1 a="<<a<<endl; } }; class base2:virtual public base { public: base2() { cout <<"base2 a="<<a<<endl; } }; class deeived : public base1, public base2 { public: derived() { cout <<"derived a="<<a<<endl; } };
32 3. 虚基类的初始化 调用各类构造函数的顺序原则如下: (1) 同一层次中先调用虚基类的构造函数(不论它在何处),再是非虚基类。 (2) 若有多个虚基类在同一层次,则按它们声明的次序。 (3) 若虚基类前又由非虚基类派生而来,则仍先非虚基类,再这虚基类。 class A { .... }; class B { .... }; class C: virtual public A, virtual public B {....}; class D: virtual public B, virtual public A {....}; class E: public C, public D { ....... }; 则建立 E 的对象时: 先 C 的 A 构造函数,C 的 B ,C 再 D ( D 的 A,B是虚只一个副本 C 中已做) 最后是 E
33 例4.14 #include <iostream.h> class base { int a; public: base(int sa) //base类构造函数 { a=sa; cout<<"构造 base 类"<<endl; } }; class base1:virtual public base { int b; public: base1(int sa, int sb):base(sa) //base1类构造函数 { b=sb; cout<<"构造 base1 类"<<endl; } }; class base2:virtual public base { int c; public: base2(int sa, int sc):base(sa) //base2类构造函数 { c=sc; cout<<"构造 base2 类"<<endl; } };
34 续上 例4.14 class derived:public base1, public base2{ int d; public: derived(int sa, int sb, int sc, int sd): base(sa),base1(sa,sb),base2(sa,ac) //derived类构造函数 { d=sd; cout<<"构造 derived 类"<<endl; } }; void main() { derived obj(2,4,6,8); }
35 4.4 应用举例 例4.4.1 单继承 #include <iostream.h> class base { private: int a; public: base(int i) { a=i; cout << "构造 base" << endl; } ~base() { cout << "析放 base" <<endl; } }; class derived:public base { private: int d; public: derived(int i, int j):base(i) //derived 构造函数 { d=j; cout << "构造 derived" << endl; } ~derived() //derived 析构函数 { cout << "析放 derived" <<endl; } };
36 续上 例4.4.1 /* class derived:public base { private: int d; base member; //对象作为数据成员 public: derived(int i, int j, int k):base(i),member(j) //derived 构造函数 { d=k; cout << "构造 derived" << endl; } ~derived() //derived 析构函数 { cout << "析放 derived" <<endl; } }; */ void main( ) { derived d(5,8); }
37 例4.4.2 多层单继承 #include <iostream.h> class base1 { private: int a; public: base1(int i) { a=i; cout << "构造 base1" << endl; } ~base1() { cout << "析放 base1" <<endl; } }; class base2:public base1 { private: int b; public: base2(int i, int j):base1(j) { b=i; cout << "构造 base2" << endl; } ~base2() { cout << "析放 base2" <<endl; } };
38 续上 例4.4.2 class derived:public base2 { private: int d; public: derived(int i, int j, int k):base2(i,j) //derived 构造函数 { d=k; cout << "构造 derived" << endl; } ~derived() //derived 析构函数 { cout << "析放 derived" <<endl; } }; void main( ) { derived d(5,8,9); }
39 例4.4.3 多继承 #include <iostream.h> class base1{ public: base1() { cout << "构造 base1" <<endl; } ~base1() { cout << "析放 base1" <<endl; } }; class base2{ public: base2() { cout << "构造 base2" <<endl; } ~base2() { cout << "析放 base2" <<endl; } }; class base3{ public: base3() { cout << "构造 base3" <<endl; } ~base3() { cout << "析放 base3" <<endl; } };
40 续上 例4.4.3 class base4{ public: base4() { cout << "构造 base4" <<endl; } ~base4() { cout << "析放 base4" <<endl; } }; class derived:public base2, public base1, public base3 { private: base4 member; derived():base2(),base1(),base3() // 可缺省 { } ~derived() { } } void main( ) { derived d; }
41 例4.4.4 园circle.cpp[例4.15] #include <iostream.h> #include <graphics.h> #include <conio.h> class location{ //定义 类 Location protected: int x,y; // x,y 为保护成员 public: location(int initx, int inity) //基类Location构造函数 { x=initx; y=inity; } }; class point:public location{ //定义 类 point,为类 Location 的公有派生类 public: point(int initx, int inity):location(initx, inity) //point 类构造函数 { } void show() //用当前颜色画点 { putpixel(x,y,getcolor()); } void hide() //抹去显示点 { putpixel(x,y,getbkcolor()); }//即用背景颜色画点 void moveto(int newx, int newy) //移动显示点
42 续上_1 例4.4.4 园circle.cpp[例4.15] { hide(); //抹去原有点 x=newx; y=newy; //设置新座标位置 show(); //画新点 } }; class circles:public point{ //定义 类 circle,为类 point 的公有派生类 private: int radius; public: circles(int initx, int inity, int initradius):point(initx, inity) { radius=initradius; } //circle 类构造函数 void show() //画一个园 { circle(x,y,radius); } void hide() //抹去已显示园 { unsigned int tempcolor; tempcolor=getcolor(); //记下当前颜色 setcolor(getbkcolor()); //将背景颜色设置为当前色 circle(x,y,radius); //用此颜色画园,相当于抹去园
43 续上_2 例4.4.4 园circle.cpp[例4.15] setcolor(tempcolor); //将当前颜色恢复到原来状态 } void expand(int expandby) //放大显示的园 { hide(); //删去原有园 radius+=expandby; //增大园半径 if (radius<0) radius=0; //避免负值 show(); //画新园 } void moveto(int newx, int newy) //移动显示的园 { hide(); x=newx; y=newy; show(); } void contract(int contractby) //缩小显示的园 { expand(-contractby); } };
44 续上_3 例4.4.4 园circle.cpp[例4.15] void main() { int gdriver=DETECT, gmode; initgraph(&gdriver,&gmode,"d:\\borlandc\\bgi"); //初始化屏幕成图形模式 circles mycircle(100,200,50); //定义一个园对象 setcolor(10); //设置当前色 mycircle.show( ); //画一个园 getch( ); for(int i=0; i<=100; i++) //慢慢移动园 { for(long j=0; j<=1000000; j++); mycircle.moveto(100+i,200); } getch( );
45 int k=0; for(i=0; i<=50; i++) //慢慢放大园 { for(long j=0; j<=1000000; j++); mycircle.expand(i-k); k=i; } getch( ); k=0; for(i=0; i<=75; i++) //慢慢缩小园 { for(long j=0; j<=1000000; j++); mycircle.contract((i-k)); k=i; } getch( ); closegraph( ); //关闭图形模式 }
46 Location Location GMseeage Circle MCircle Data_rec 虚 虚 teacher student staff 例4_16在圆内显示正文 例4_17简单的大学管理系统
47 例4.4.5 单一继承实例 void main() { cbox.SetColor(5); cbox.SetWidth(3); cbox.SetHeight(50); cbox.print( ); } #include <iostream.h> class BoxShape { public: int width,height; int SetWidth(int w) { width=w; } int SetHeight(int h) { height=h; } }; class ColorBoxShape:public BoxShape { public: int color; void SetColor(int c) { color=c; } void print( ) { cout << "颜色是:"<<color<<" 宽是:"<<width<<" 高是:"<<height<<endl; } }; ColorBoxShape cbox;
48 例4.4.6 class Furniture //创建一个公共的父类 { int color, width, height; public: Furniture(int, int, int); //Furniture 构造函数声明 int GetColor() { return color; } int GetWidth() { return width; } int GetHeight() { return height; } }; Furniture::Furniture(int c, int w, int h) //Furniture 构造函数 { color=c; width=w; height=h; } //以上是Furniture类定义 class BookShelf:public Furniture //派生一个类 BookShelf { int shelves; public: BookShelf(int, int, int, int); //BookShelf 构造函数声明 int GetShelves() { return shelves; } void print() { cout<<"书架数据:"<<shelves<<endl; cout<<"颜色:"<<GetColor()<<endl; cout<<" 宽:"<<GetWidth()<<endl; cout<<" 高:"<<GetHeight()<<endl; } };
49 续上 例4.4.6 BookShelf::BookShelf(int c, int w, int h, int s):Furniture(c,w,h) { shelves=s; } //以上是BookShelf类定义 class Table:public Furniture { int drawers, material; public: Table(int, int, int, int, int); //Table 构造函数声明 int GetDrawers() { return drawers; } int GetMaterial() { return material; } void print() { cout<<"书桌数据:"<<drawers<<" "<<material<<endl; cout<<"颜色:"<<GetColor()<<endl; cout<<" 宽:"<<GetWidth()<<endl; cout<<" 高:"<<GetHeight()<<endl; } }; Table::Table(int w, int h, int c, int d, int m):Furniture(c,w,h) { drawers=d; material=m; } //以上是Table类定义 void main() { Table d(1,2,3,4,5); d.print(); BookShelf b(10,11,12,13); b.print(); }
50 例4.4.7 派生类中访问基类成员的例子 class base { //...... public: void fun(); }; class derived1:private base { public: void funder1(){ 可以访问fun() } }; class derived2:public derived1 { public: void funder2(); { 可以访问funder1(),不能访问fun() } };