版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、第十篇 继承,虚函数和多态 本章中我们将讨论和面向对象编程直接相关的三个C+特性:继承,虚函数和多态。继承是允许一个类继承另外一个类特征的特性。使用继承,我们通过一个类来定义一组相关对象的通用特征。这个类可以被另外一些更具体的类继承,每个类都可以增加其特有的属性。而虚函数正是以类的继承为基础的。虚函数支撑了多态性,也就是“同一个接口,多种实现方式”的面向对象的思想。必备技能10.1:继承的基础知识在C+中,被继承的类称为基类。继承别的类的类叫做派生类。因此可以说派生类是基类的特殊化。派生类继承了基类中的所有成员,并增加了自己所特有的成员。继承是由基类和派生类共同作用实现的。
2、这是通过在声明派生类的时候指明其基类来完成的。下面我们通过一个简短的示例程序来讨论和继承相关的几个特性。下面的程序创建了一个基类叫做TwoDShape,用于存储一个二维对象的宽带和高度,还定义了一个派生类叫做Triangle。特别注意下面类Triangle的声明方式。/ 一个简单的类的继承示例 #include <iostream>#include <cstring>using namespace std; /二维对象类class TwoDShapepublic:
3、160; double width; double height; void showDim() cout << "Width and height are " &
4、#160; << width << " and " << height << "n" /Triangle类是从TwoDShape类中继承而来的class Triangle : public TwoDShapepubli
5、c: char style20; double area() return width * height / 2; void showStyle()
6、0; cout << "Triangle is " << style << "n" int main() Triangle t1; Triangle
7、0;t2; t1.width = 4.0; t1.height = 4.0; strcpy(t1.style,"isosceles"); t2.width = 8.0; t2.height = 12.0;
8、60; strcpy(t2.style,"right"); cout << "Info for t1:n" t1.showStyle(); t1.showDim(); cout << "n"
9、 cout << "Info for t2:n" t2.showStyle(); t2.showDim(); cout << "Area is " << t2.area() << "n&
10、quot; return 0; 上面程序的输出结果如下:Info for t1:Triangle is isoscelesWidth and height are 4 and 4 Info for t2:Triangle is rightWidth and height are 8 and 12Ar
11、ea is 48其中,TwoDShape类定义了二维形状的通用属性,比如正方形,长方形,三角形等等。而Triangle(三角形)类则是TwoDShape类的具体的例子。三角形类包含了TwoDShape这个类的所有成员,并且还增加了字段style,函数area()和showStyle()。关于三角形类型的描述存储在style字段中,area()函数用于计算并返回三角形的面积,showStyle()函数用于显示三角形的类型。下面的代码行就显示了Triangle类是怎么继承TwoDShape类的:class Triangle : publ
12、ic TwoDShape其中,TwoDShape是Triangle类所继承的类,也就是基类。正如这个示例程序演示的那样,类继承的语法是很简单的,也是很方便使用的。由于Triangle类包含了它的基类TwoDShape的所有成员,因此它就可以在area()函数中访问width和height。同样,在main()函数中,t1,t2都可以直接访问width和height,就像它们是Triangle的一部分一样。图10-1从概念上刻画了TwoDShape和Triangle类的直接关系。图10-1 Triangle类的构成另外的一点:尽管TwoDShape是Triangle类的基类,
13、它仍然是一个完全对立的类。作为一个派生类的基类并不是说这个类就不能单独使用了。声明继承关系的通用形式如下:class 派生类: 访问限定符 基类 / 派生类的定义体 其中的访问限定符是可选的。然而,如果需要明确指定,只能是public, private或者是protected。我们将在本章的后面对它们进行更多的讨论。到目前为止,我们所有的继承关系都将使用public。使用public的继承关系意味着基类中所有的公有的成员在派生类中依然是公有的。继承的一个主要好处就是一旦我们创建了一组对象所共有特性的基类后,我们就
14、可以创建任意数量的具体特殊性质的派生类。每个派生类都可以精确地根据分类来进行剪裁。例如,下面就是另外一个从TwoDShape类继承的类Rectangle,它封装了对矩形的操作:class Rectangle:public TwoDShapepublic: bool isSquare() if ( width = height )&
15、#160; return true; else
16、0; return false; double area() return width * heig
17、ht; 这里的Rectangle类包含了TwoDShape类的全部成员,并增加了函数isSquare(),用来判断该矩形是不是正方形。同时,增加了函数area(),用来计算矩形的面积。继承与成员的访问权限正如我们在第八篇中学习到的那样,类的成员经常会被声明为是私有的,以便避免未经授权的使用或者篡改。继承机制并没有推翻私有访问权限的限制。然而,尽管派生类中包含了基类的所有成员,但是它不能访问基类中的那些私有成员。例如,如果在TwoDShape类中width和height都是私有的,如下代码所示,那么Triangle类就是不能访问它们的。/二维对象类c
18、lass TwoDShape / width 和 height是私有的 double width; double height; public: void showDim() cou
19、t << "Width and height are " << width << " and " << height << "n"
20、; /Triangle类是从TwoDShape类中继承而来的class Triangle : public TwoDShapepublic: char style20; double area() return width * h
21、eight / 2; /错误,Triangle类不能访问基类的私有成员 void showStyle() cout << "Triangle is " << style <<
22、"n" 上面中Triangle类将不能被成功编译。这是因为其中的area()函数中引用了基类的私有数据成员width和height,这是违反规则的。由于width和height成员现在是私有的,只有TwoDShape类本身可以访问它们。其派生类是无权访问它们的。乍看起来,我们可能会认为派生类不能访问基类的私有数据成员貌似是一种过分严格的限制,因为在很多情况下,这将使得我们无法访问私有的成员。幸运的是,实际情况并非如此,C+提供了几种不同的方法来解决这个问题。其中之一就是使用protected(保护)成员,这点我们将在下面的小节中
23、进行讨论。还有一种方法就是提供公有的函数来实现对私有数据的访问。正如我们在前面篇章中看到的那样,C+程序员通常会通过公有的函数来实现对私有数据成员的访问。提供访问私有数据成员的函数被称为是访问函数。下面代码中,我们就采用了访问函数的方式来提供对TwoDShape类的私有数据成员的访问:/ 一个简单的类的继承示例 #include <iostream>#include <cstring>using namespace std; /二维对象类class TwoDShape
24、 double width; double height;public: void showDim() cout << "Width and height are "
25、0; << width << " and " << height << "n" double getWidth() return width; &
26、#160; double getHeight() return height; void setWidth(double w ) width = w void setHeight(double h ) height = h; /T
27、riangle类是从TwoDShape类中继承而来的class Triangle : public TwoDShapepublic: char style20; double area() /return width * height / 2;
28、 return getWidth() * getHeight() / 2; void showStyle() cout << "Triangle
29、 is " << style << "n" int main() Triangle t1; Triangle t2; /t1.width = 4.0; /t1.height =
30、0;4.0; t1.setWidth(4.0); t1.setHeight(4.0); strcpy(t1.style,"isosceles"); /t2.width = 8.0; /t2.height = 12.0; t1.setWidth(8.0)
31、; t2.setHeight(12.0); strcpy(t2.style,"right"); cout << "Info for t1:n" t1.showStyle(); t1.showDim(); co
32、ut << "n" cout << "Info for t2:n" t2.showStyle(); t2.showDim(); cout << "Area is " << t2
33、.area() << "n" return 0; 练习1. 基类是通过怎样的方式被派生类继承的?2. 派生类中是否包含了基类中的成员?3. 派生类是否可以访问基类中私有的成员? 必备技能10.2:对基类成员的访问控制正如我们在前面所讨论到的那样,当一个类继承了另外一个类后,基类的所有成员也都会变成派生类的成员。然而,在派生类中,基类成员的可访问性是由派生类继承基类的方式来决定的,也就是由继承的访问限定符来决定的。派生类继承基类
34、时的访问限定符只能是public,private或者protected。当我们没有指定访问限定符的时候,如果基类是一个类,那么缺省的访问限定符就是private。如果基类是一个结构体,则缺省的访问限定符是public。下面,我们就来讨论一下public和private继承方式的区别。protected的继承方式我们将在下节中进行讨论。当派生类以公有的(public)的方式继承基类的时候,基类的所有公有成员就会变成是派生类的公有成员。然而,基类的私有成员则永远会是基类的私有成员,派生类是不能访问的。例如,在下面的程序中,B的公有成员变成了D的共有成员,因此可以被程序的其它部分访问。/演示公有继承
35、#include <iostream>using namespace std;class B int i,j;public: void set( int a, int b ) i = a;
36、 j = b; void show() cout << i << " " << j << "n&
37、quot; class D : public B int k;public: D(int x) k = x; void sh
38、owk() cout << k << "n" / i = 10 /错误!i在B类中是私有的成员,派生类是不能访问的。 int main()
39、; D ob(3); ob.set(1,2); /访问基类的共有成员 ob.show();/访问基类的共有成员 ob.showk();/访问派生类的共有成员 return 0;既然set()和show()函数在基类B中都是公有的,因此他们是可以在main()函数中D类的对象上被调用的。i和j在基类B中都是私有的,这是下面的代码
40、行 / i = 10 /错误!i在B类中是私有的成员,派生类是不能访问的。被注释掉的原因。D类是不能访问B的私有成员的。和公有继承想对应的就是私有继承。当以私有的方式继承基类的的时候,基类中所有的公有成员都在派生类中变成了私有成员。例如,下面的程序不能成功编译,就是因为set()和show()现在对于D类来说都是私有的,因此不能在main()函数中被调用。/演示私有的继承方式,改程序不能被成功编译#include <iostream>using namespace std;class
41、0;B int i,j;public: void set( int a, int b ) i = a; j = b;
42、; void show() cout << i << " " << j << "n" class D : private B&
43、#160; int k;public: D(int x) k = x; void showk()
44、60; cout << k << "n" / i = 10 /错误!i在B类中是私有的成员,派生类是不能访问的。 int main() D ob(3);
45、ob.set(1,2); /访问基类的共有成员 ob.show();/访问基类的共有成员 ob.showk();/访问派生类的共有成员 return 0;小结:当基类以private的方式被继承的时候,其所有的共有成员都变成了派生类的私有成员。这就意味着,它们可以被派生类的成员调用,但是不能被程序的其它部分调用。专家答疑问:我知道在Java编程中使用父类和子类概念,这两个概念在C+中有什么含义?答:Java中的父类就是C+中的基类。Jav
46、a中的子类就是C+中的派生类。通常我们在这两个语言中都能听到这两种术语。但是在本书中,我们将使用标准的C+术语。另外,在C#中也是使用基类和派生类的术语。必备技能10.3:使用保护的成员正如我们所讨论的那样,基类的私有成员在派生类中是不能被访问的。这样一来,如果派生类想要访问基类的成员,似乎只能把这些成员在基类中声明为公有的了。但是,这样以来,程序中的其它代码也是可以访问这些公有成员的,这不是我们想要的。幸运的是,C+允许我们创建保护的成员,从而没有必要把派生类访问的成员在基类中声明为公有的。保护的成员在类的继承关系中是公有的,但是对于继承关系之外的代码来说又是私有的。保护成员的创建是通过使用
47、protected修饰符来完成的。当类的一个成员被声明为protected的时候,该成员就是私有的,只有一种情况例外。就是当该保护成员被继承的时候。此时,派生类是可以访问基类的保护成员的。因此,通过使用保护成员,我们就可以创建对于自身来说是私有的,但是派生类又可以访问的类的成员。protected修饰符也可以用于结构体。下面的程序演示了保护成员/演示保护成员#include <iostream>using namespace std; class Bprotected: int
48、;i,j;public: void set( int a, int b ) i = a; j = b; void
49、 show() cout << i << " " << j << "n" class D : public B i
50、nt k;public: /D可以访问B类中的i和j。这是因为他们是保护的,而非私有的。 void setk() k = i * j; void showk()
51、60; cout << k << "n" int main() D ob; ob.set(1,2); /访问基类的共有成员
52、 ob.show();/访问基类的共有成员 ob.setk(); ob.showk();/访问派生类的公有成员 return 0; 其中由于D公有地继承了B类,并且i和j在B类中被声明为保护成员,所以D的函数setk()就可以访问它们。如果i和j被声明为是private的,那么D就不能访问它们,程序也就不能成功编译了。当派生类以公有的方式继承基类的时候,基类中的保护成员在派生类中也是保护成员。当基类被以私
53、有的方式继承的时候,基类的保护成员在派生类中就变成了私有的成员了。protected修饰符在声明类的时候可以出现在任何位置,但是通常它是被写在类的私有成员之后,而在共有成员之前。因此,最常用的完整的类的声明形式如下:class 类名private:/私有成员,缺 省就是私有的。protected:/保护成员public:/共有成员;当然,其中的protected是一个可选项。除了上面的类的保护成员外,关键字protected也可以用于基类被继承时候的访问限定符。当基类以保护的方式被继承的时候,其所有的公有和保护成员在派生类中都变成了保护成员。例如:class D&
54、#160;: protected B /.;那么,B中所有的非私有成员在D中都变成了保护的。练习:1. 当基类以private的方式被继承的时候,它的公有成员在派生类中都成了私有的成员。对吗?2. 基类中的私有成员可否通过继承的方式在派生类中变成共有的?3. 在继承关系中,使用哪个访问限定符可以使得基类的成员可以被访问,而不是私有的不能访问。专家答疑问:能对public,protected和private进行一个总结吗?答:当类的成员被声明为共有的,它是可以被程序中任何的代码访问的。当类的成员被声明
55、私有的,它只能被该类本身的成员访问。派生类不能访问基类中的私有成员。当一个成员被声明为保护的时候,它只能被自身类及其子类访问。所以,保护成员可以被继承但是在继承关系中则为私有的。当基类以公有的方式被继承的时候,它的公有成员在派生类中依然是公有的,它的保护成员在派生类依然是保护的。当基类被以保护的方式继承的时候,它的公有和保护成员则在派生类中都变成了保护的。当基类被以私有的方式继承的时候,它的公有和保护成员在派生类中都是私有的。无论什么情况,基类中私有的成员都永远是该基类私有的。构造函数与继承在继承关系中,基类和派生类有可能都有自己的构造函数,这就存在一个很重要的问题:到底调用哪个构造函数来生成
56、派生类的对象了,基类的构造函数,还是派生类的构造函数,或者两者都调用?这个问题的答案是这样的:基类的构造函数负责构建该对象的基类部分,派生类的构造函数负责构建该对象的派生类部分。这样做是合理的,这是因为基类是不能感知并访问派生类的成员的。因此它们各自部分的构造必须是分开的。前面的示例程序中采用了C+提供的缺省的构造函数,因此没有什么问题。但是,实际应用中大部分的类都会定义构造函数。这里我们就针对这种情况进行讨论。当只有派生类中定义了构造函数的时候,处理起来很简单:直接生成派生类的对象。其中基类的部分自动调用缺省的构造函数。例如,下面是Triangle类的另外一个版本,这个版本中,我们为Tria
57、ngle类定义了构造函数。同时,还把style成员声明为私有的,它在构造函数中被赋值。/ 为Triangle类定义构造函数 #include <iostream>#include <cstring>using namespace std; /二维对象类class TwoDShape double width; double height;public:
58、60; void showDim() cout << "Width and height are " << width <<
59、 " and " << height << "n" /访问函数 double getWidth() return width; double getHeight() return
60、160;height; void setWidth(double w ) width = w void setHeight(double h ) height = h; /Triangle类是从TwoDShape类中继承而来的class Triangle : public
61、160;TwoDShape char style20; public: / 构造函数 Triangle( char *str, double w, double h) /初始化TwoDShape的部分
62、60; setWidth(w); setHeight(h); /对Triangle类特有的部分进行初始化 strcpy(style,str);
63、; double area() return getWidth() * getHeight() / 2; void showStyle() &
64、#160;cout << "Triangle is " << style << "n" 其中,Triangle类的构造函数对从TwoDShape类中继承来的以及自己增加的成员都进行了初始化。当基类和派生类中都定义了构造函数的时候,情况就有点复杂,因为此时基类和派生类的构造函数都是要被执行的。必备技能10.4:调用基类的构造函数当基类中定义了构造函数的时候,派生类必须显式地调用该构造函数来对对象的
65、基类部分进行初始化。派生类通过使用扩展的派生类构造函数的声明方法来调用基类的构造函数。这种扩展的形式如下:派生类的构造函数(参数列表): 基类的构造函数(参数列表); /派生类构造函数体其中,基类的构造函数就是派生类继承的基类的名称。注意,在上面的形式中使用了一个冒号来把基类和派生类的构造函数分开。如果一个派生类继承了多个基类,那么这些基类的构造函数都是通过冒号来分隔的。下面的程序演示了如何把参数传入到基类的构造函数中。其中为TwoDShape类定义了一个构造函数用来完成对width和height属性的初始化。/ 为TwoDSh
66、ape类增加构造函数#include <iostream>#include <cstring>using namespace std;/二维对象类class TwoDShape double width; double height;public: /构造函数 TwoDShape(double w,double
67、 h) width = w; height = h; void showDim()
68、0; cout << "Width and height are " << width << " and " << height << &
69、quot;n" /访问函数 double getWidth() return width; double getHeight() return height; void setWidth(double w )
70、 width = w void setHeight(double h ) height = h; /Triangle类是从TwoDShape类中继承而来的class Triangle : public TwoDShape char style20;public: /
71、;构造函数 Triangle( char *str, double w, double h):TwoDShape(w,h) strcpy(style,str); double area()
72、 return getWidth() * getHeight() / 2; void showStyle() cout << "Triangle is &quo
73、t; << style << "n" int main() Triangle t1("isosceles",4.0,4.0); Triangle t2("right", 8.0, 12.0); cout <<
74、"Info for t1:n" t1.showStyle(); t1.showDim(); cout << "Area is " << t1.area() << "n" cout <<&
75、#160;"n" cout << "Info for t2:n" t2.showStyle(); t2.showDim(); cout << "Area is " << t2.area() <
76、< "n" return 0;其中,Triangle()通过调用了TwoDShape的构造函数并把w和h的值传入其中来完成对width和height的初始化,而不用自己再对其进行初始化了。它只需要对自己特有的值进行初始化即可,那就是style。这就使得TwoDShape类可以自由地按照自己的方式来构建自己的子对象。进一步来讲,TwoDShape类可以自由增加不为派生类所感知的功能,避免了既存代码的修改。基类中定义的任何形式的构造函数都是可以被派生类的构造函数调用的。真正被调用的是那个和传入参数相匹配的构
77、造函数。例如,下面的代码中队TwoDShape和Triangle类机进行了扩展,增加了构造函数:/ 为TwoDShape类增加构造函数#include <iostream>#include <cstring>using namespace std;/二维对象类class TwoDShape double width; double height;public:
78、60;/缺省的构造函数 TwoDShape() width = height = 0; /构造函数 TwoDShape(double w,double h)
79、0; width = w; height = h; /构造高度和宽度相等的对象 TwoDShape(double x)
80、0; width = height = x; void showDim() cout << "Width and height are " &
81、#160; << width << " and " << height << "n" /访问函数 double getWidth()
82、; return width; double getHeight() return height; void setWidth(double w ) width = w void setHeight(double h ) hei
83、ght = h; /Triangle类是从TwoDShape类中继承而来的class Triangle : public TwoDShape char style20;public: /缺省的构造函数。这将自动调用TwoDShape的缺省构造函数 Triangle()
84、60; strcpy(style,"unknown"); /有三个参数的构造函数 Triangle( char *str, double w, double h):TwoDShape(w,h) strcpy(styl
85、e,str); /构建一个等腰三角形 Triangle(double x):TwoDShape(x) strcpy(style,"isoscoles"); double area()&
86、#160; return getWidth() * getHeight() / 2; void showStyle() cout << &qu
87、ot;Triangle is " << style << "n" int main() Triangle t1; Triangle t2("right", 8.0, 12.0); Triangle t3(4.0);
88、0; t1 = t2; cout << "Info for t1:n" t1.showStyle(); t1.showDim(); cout << "Area is " <<
89、;t1.area() << "n" cout << "n" cout << "Info for t2:n" t2.showStyle(); t2.showDim(); cout <
90、;< "Area is " << t2.area() << "n" cout << "n" cout << "Info for t2:n" t3.showStyle();
91、160; t3.showDim(); cout << "Area is " << t3.area() << "n" cout << "n" return 0;上面程序的输出结果如下:Info for&
92、#160;t1:Triangle is rightWidth and height are 8 and 12Area is 48Info for t2:Triangle is rightWidth and height are 8 and 12Area is 48Info for t2:Triangle is is
93、oscolesWidth and height are 4 and 4Area is 8练习:1. 派生类如何执行基类的构造函数?2. 是否可以为基类的构造函数传入参数?3. 哪个构造函数负责完成派生类对象中基类部分的初始化,是基类定义的构造函数还是派生类中定义的构造函数?工程10-1 扩展Vehicle类在该工程中,我们针对第八章中的Vehicle类创建一个子类。回忆一下,Vechile类封装了汽车的信息,包括载客人数,邮箱容量以及每加仑油能跑的里程数。我们可以
94、以Vechile类作为基础来创建更多更具体的类。例如,卡车就是一种Vechile。卡车的一个重要属性就是它的载重量。因此我们可以采用集成Vehicle类的方式来创建Truck类,只需要增加一个实例变量来表示它的载重量。在该工程中,我们就将创建这样的Truck类。其中,我们会把Vehicle的实例变量声明为private,而增加访问函数来获取它们的值。步骤:1. 创建一个文件,名称TruckDemo.cpp,把第八章中最后一个版本的Vehicle的实现拷贝过来。2. 创建Trucnk类,如下:/在Vechile类的基础上增加特有的属性class Truck
95、;: public Vehiclepublic: int cargocap; /载重量,单位:磅 /构造函数 Truck( int p , int f, int m, int c ) : Vehicle(p,f,m) &
96、#160; cargocap = c; /载重量的访问函数 int get_cargocap() return cargocap; 这里,Truck类继承了Vehicle类,并增加了ca
97、rgaocap成员。因此,Truck类中包含了通用类Vechile中的全部元素。增加的只是Trunck特有的元素。3. 完整的程序如下:#include <iostream>using namespace std;/声明Vehicle类class Vehicle int passengers; / 载客人数 int fuelcap; / 油箱容量&
98、#160; int mpg; / 每加仑油能跑的里程数public: /构造函数 Vehicle(int p, int f, int m) passengers
99、0;= p; fuelcap = f; mpg = m; int range() /计算并返回汽车能跑的最大里程数,此处为函数声明
100、; return mpg * fuelcap; /访问函数 int get_passangers() return passengers; int get_fuelcap() return fuelcap;
101、 int get_mpg() return mpg; /在Vechile类的基础上增加特有的属性class Truck : public Vehiclepublic: int cargocap; /载重量,单位:磅 /构造函数 Truck( int p , int
102、f, int m, int c ) : Vehicle(p,f,m) cargocap = c; /载重量的访问函数 int get_cargocap()
103、160; return cargocap; int main() /生成Trunck类的对象 Truck semi(2,200,7,4400); Truck pickup(3,28,15,2000); int dist = 252
104、; cout <<"Semi can carry " << semi.get_cargocap() << " pounds.n" cout << "It has a range of " << semi.ra
105、nge() << " miles.n" cout << "To go " << dist << " miles semi needs " << dist/semi.get_mpg() <<
106、60;" gallons of fuel.nn" cout <<"Pickup can carry " << pickup.get_cargocap() << " pounds.n" cout << "It has a
107、range of " << pickup.range() << " miles.n" cout << "To go " << dist << " miles pickup needs "
108、 << dist/pickup.get_mpg() << " gallons of fuel.n" return 0;4. 上面程序的输出如下:Semi can carry 4400 pounds.It has a range of 1400 miles.To go 252 miles
109、160;semi needs 36 gallons of fuel.Pickup can carry 2000 pounds.It has a range of 420 miles.To go 252 miles pickup needs 16 gallons of fuel.5. 我们还可以从Vehicle类派生出许多别的类。比如,下面的代码框架
110、就创建了一个越野车的类,它存储了车辆距离地面的净距离:class off-road : public Vechile int groundClearance; / 距离地面净距离,单位英寸public: / .;重要的一点是,一点我们创建了具有对象通用属性的基类,我们就可以继承该类从而创建特殊的类。每个派生类只是简单地增加自己特有的属性即可,这就是继承的本质。必备技能10.5:多层继承到目前为止,我们使用到的继承关系只是一个
111、基类和一个派生类。然而,我们是可以创建任意多层的继承关系的。正如在前面所提到的那样,把一个派生类作为另外一个类的基类是完全可以接受的。例如,有三个类A,B和C。C可是是从B继承而来的,同时B可以是从A继承而来的。当发生这样的情况的时候,每个派生类都继承了它所有基类的所有属性。针对刚才的例子,C就继承了A和B的全部属性。为了理解多层继承的作用,我们来研究下面的程序。其中,Triangle类被作为基类来创建派生类ColoreTriangle。ColorTriangle就拥有了Triangle类和TwoDShape类的全部属性。/多层继承#include <iostream>#include <cstring>using name
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 直线与圆课件-2026届高三数学二轮专题复习
- 早教课件考试试题及答案
- 2026九年级上语文我看写作手法分析
- 烟草工艺学试题及答案
- 2026二年级数学下册 万以内数能力测试
- 企民双入户制度
- 企业心理咨询制度
- 乌鲁木齐铁路局奖惩制度
- 广东金融学院奖惩制度
- 高中生学习组奖惩制度
- 教育局培训学校退费制度
- 中药膏摩技术
- GB/T 46871-2025二氧化碳捕集、运输和地质封存提高原油采收率的二氧化碳封存
- 生产统计管理岗位操作规范
- 2026年湖南交通职业技术学院单招综合素质笔试参考题库带答案解析
- 针刺伤处理课件
- 2026年江苏卫生健康职业学院高职单招职业适应性测试备考试题有答案解析
- 2026年娱乐行业互动电影报告及未来五至十年沉浸式娱乐报告
- 2023年阜阳科技职业学院单招职业适应性测试题库附答案解析
- 2026年萍乡卫生职业学院单招职业技能考试必刷测试卷及答案1套
- 2025至2030中国私人飞机行业调研及市场前景预测评估报告
评论
0/150
提交评论