《C与C++程序员面试宝典》第9章面向对象与类.pdf
第 9 章面向对象与类面向对象的概念是面向过程概念之后推出的,是高级语言的特征,也是当年开发语言的主流。面向对象主要解决的问题有3 个,即软件和代码重用性比较差、软件和代码的可维护性比较差及软件不能满足客户的需求。类是面向对象语言最重要的进化,通过将对象抽象为类,编程者可以将具体问题抽象化,极大的增强了软件模型的描述能力。9.1 面 向 对 象 的 基 本 知 识面向对象是现实世界中模型的自然延伸,现实世界中的所有实体都可以看作是对象。对象和对象直接可以通过消息来相互作用。面向对象是高级编程语言的特征,它以对象为语言的中心,用消息来进行驱动。面试题9 6 面向对象与面向过程的区别【出现频率】【关键考点】面向对象的概念;面向过程的概念。【考题分析】面向对象至今还没有统一的概念。在这里把它定义为:按人们认识客观世界的系统思维方式,采用基于对象(实体)的概念建立模型,模拟客观世界分析、设计、实现软件的办法。通过面向对象的理念使计算机软件系统能与现实世界中的系统一一对应。对象是指现实世界中各种各样的实体。它可以指具体的事物也可以指抽象的事物。例如,整 数 1、20、300、同学、苹果、飞机、规则、法律、法规、表单等。每个对象都有自己的内部状态和运动规律,如阿梁同学具有名字、外貌、身高等内部状态,具有吃饭、睡觉、逛街、打球、散步等运动规律。在面向对象概念中编程者把对象的内部状态称为属性、运动规律成为方法或事件。面向对象设计是把分析阶段得到的需求转变成符合成本和质量要求的、抽象的系统实现方案的过程。从面向对象分析到面向对象设计,是一个逐渐扩充模型的过程。面向对象中任何对象都可以归属于某类对象,任何对象都是某一类对象的实例。类在面向对象中描述了一组具有相同的特性和行为的对象。C+就是一种面向对象的高级语言。面向过程是一种以过程为中心的编程思想。面向过程分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,在使用的时候一个一个依次调用。面向过程其实是第9章 面向对象与类最为实际的一种思考方式,就算是面向对象的方法也是含有面向过程的思想。可以说面向过程是一种基础的方法。它考虑的是实际的实现。一般的面向过程是从上往下步步求精。在面向过程中,最重要的是模块化的思想方法。C语言就是一种典型的面向过程语言。【答案】面向过程是一种以过程为中心的编程思想,以算法进行驱动。面向对象是一种以对象为中心的编程思想,以消息进行驱动。面向过程编程语言的组成为:程序=算法+数据,面向对象编程语言的组成为:程序=对象+消息。面试题9 7 面向对象的特征是什么【出现频率】【关键考点】面向对象的特征【考题分析】面向对象语言的3个要素为封装、继承和多态。封装就是将抽象得到的数据和行为(或功能)相结合,形成一个有机的整体,也就是将数据与操作数据的源代码进行有机的结合,形 成“类”,其中数据和函数都是类的成员。封装的目的是增强安全性和简化编程,使用者不必了解具体的实现细节,而只是要通过外部接口和特定的访问权限来使用类的成员。继承是指可以使用现有类的所有功能,继承可以使一个对象直接使用另一个对象的属性和方法,并在无需重新编写原来的类的情况下对这些功能进行扩展。通过继承创建的新类称为“子类”或“派生类”。被继承的类称为“基类”、“父类”或“超类”。继承的过程是从一般到特殊的过程。多态性是允许将父对象设置成为和一个或多个它的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。例如a:=b;多态性使得能够利用同一类(基类)类型的指针来引用不同类的对象,以及根据所引用对象的不同,以不同的方式执行相同的操作。面向对象语言比较面向过程语言有类的概念。类就是把一组具有相同的方法和属性的对象归属为一起。面向对象中,所有对象都可以归属为一个类。【答案】面向对象的3个要素为:封装、继承、多态。面向对象中所有的对象都可以归属为一个类。9.2类类是面向对象程序设计语言中最重要的概念之一,其本质上是对某种类型的对象定义变量和方法的原型。它表示对现实生活中一类具有共同特征的事物的抽象,类是面向对象编程的基础。101 第2篇 C/C+基础知识面试题9 8 类和结构有什么区别【出现频率】【关键考点】类的概念;结构的概念。【考题分析】类是对某种类型的对象定义变量和方法的原型。它表示对现实生活中一类具有共同特征的事物的抽象,是面向对象编程的基础。类是对某个对象的定义。它包含有关对象动作方式的信息,包括它的名称、方法、属性和事件等。类本身并不是对象,因为它不存在于内存中。当引用类的代码运行时,类的一个新的实例,即对象,就在内存中创建了。一个类可以在内存中创建多个相同类型的对象。类定义的一般形式如下:class Name(public:类的公有接口private:私有的成员函数私有的数据成员定义);其中public表示公开访问权限,而 private表示只有类自身才具有访问权限。类成员有3 种不同的访问权限。公 有(public)成员可以在类外访问:私 有(private)成员只能被该类的成员函数访问;保 护(protected)成员只能被该类的成员函数或派生类的成员函数访问。类体定义类的成员,它支持两种类型的成员,具体如下。数据成员,它们指定了该类对象的内部表示;成员函数,他们指定了该类的操作。结构是用户定义的值类型。与类相似,结构可以包含构造函数、常数、字段、方法、属性、索引器、运算符和嵌套类型。结构定义的一般形式如下:struct test(float a;int b;);下面来使用结构和类来实现同样的一个输出日期的功能。示例代码如下:#include using namespace std;struct Datel/定义结构体 102 第9 章面向对象与类int year;int month;int day;void display(););void Datel:display()(cout ”您输入的日期如下:”;cout year “年 month “月 day H;class Date2/定义类int year;int month;int day;public:Date2()()Date2(int yearO,int monthO,int dayO)/带参数的构造函数(year=yearO;month=monthO;day=dayO;void getDate()(cout ”您输入的日期如下:”;cout year “年 month “月 f2();();delete m_j;return 0;在上面代码中,fl()是一个普通的重载。调 用 m-fl();会调用A 类中的f l(),它是由 A 类定义的,这样就调用这个类的函数。&()是虚函数。m-f2()”,会调用m J 保存的对象中对应的这个函数。这是由于“new B()”对象。口()与f2()一样,但是在基类中不需要写函数实现。【答案】包含纯虚函数的类称为抽象类。抽象类把有共同属性或方法的对象抽象成一个类。104 第9章 面向对象与类9.3类 成 员在 C+中,运行库可以定义类的成员,类的成员包括数据、函数和嵌套类型,它们一起组成了类。面试题1 0 0 成员变量有哪些访问方式【出现频率】【关键考点】成员变量的概念;成员变量的访问方式。【考题分析】在类的成员中,类的数据变量就是类的成员变量。在 C/C+中,类的成员变量有3 种访问方式,分别为private、public和 protected,它们的访问权限如下所示。private:只能由该类中的方法访问,是私有变量,不能被该类的对象访问;protected:可以被该类中的方法和其友元函数访问,但不能被该类的对象访问;public:可以被该类中的方法和其友元函数访问,是公有变量,也可以由该类的对象访问。在 C 语言中,如果没有声明访问权限,默认的访问权限是public,而在C+中默认的访问权限是private,所以在类中的成员中如果需要外部调用都需要加上关键字public声明为公有类型,这一特性同样使用于类中的成员函数。【答案】成员变量根据访问权限有privateprotect和 public 3 种访问方式。面试题1 0 1 成员变量有哪些访问控制方式【出现频率】【关键考点】为什么要访问控制;成员变量有哪些访问控制方式。【考题分析】在 C+中,对成员变量进行访问控制主要有以下几个目的。对普通函数和其他类的成员函数来说,访问控制可以保护类的成员变量数据不被随便修改。类可以对它本身的内部数据维护负责,只有类自己才能够访问自己的私有成员变量。类的外部接口,把一个类分成公有的和受保护的两部分,对于使用者来说它只要 105 第2篇 C/C+基础知识会用就可以,无须了解类的内部完整结构,起到黑盒的效果,使用起来更加轻松简单。类与其他代码的关联性,类的功能是独立的,不需要依靠应用程序的运行环境,这个程序可以用它,另外一个也可以用它,使得你可以轻易实现类的相互替换。成员变量的访问控制方式和成员变量的访问方式一样,有 private、protect和 public3 种。下面举一个例子来看看类是怎样实现访问控制的。示例代码如下:#include#include ballscore.hHusing namespace std;class getscore(protected:const static int goods=5;const static int bads=-3;float gradescore;public:float GetGS(float good,float bad)/得分/扣分/平均得分/good为得分次数,bad为失分次数tGradescore=(good*goods+bad*return gradescore;);bads)/(good+bad);/返回平均得分void main()(Ballscore eff;coutj ef f.GetGS(10,3);j im.gradescore=5.5cin.get();)/注意:想修改jim的平均成绩是不允许的在上面代码中实现了一个计算平均得分的类,类中有一个公共的计算平均得分的方法和受保护的得分、失分和平均得分属性。在主函数的调用中,gradescore属性是受保护的,所以不可以在外部修改它的值.而 GetGS方法是可以在外部被调用的。【答案】在 C/C+中,是通过声明private、protect和 public 3 种访问权限来对成员变量进行访问控制的。面试题1 0 2 如何访问静态成员【出现频率】【关键考点】静态成员的概念;如何访问静态成员。【考题分析】声 明 为 static的类成员能在类的范围内共享,这样的类成员就是类的静态成员。在类中,静态成员可以实现多个对象之间的数据共享,并且使用静态数据成员还不会破坏隐藏 106,第9章 面向对象与类的原则,因此保证了安全性。因此,静态成员是类的所有对象中共享的成员,而不是某个对象的成员。使用静态数据成员可以节省内存,因为它是所有对象所公有的。因此,对多个对象来说,静态数据成员只会在内存中开辟一块存储空间,供所有对象共用,静态成员在类加载的时候就存在于内存中。静态数据成员的值对每个对象都是一样,但它的值是可以更新的。只要对静态数据成员的值更新一次,保证所有对象存取更新后的相同的值,这样可以提高时间效率。类的静态成员是可以独立访问的,也就是说,不需要创建类的实例就可以访问静态成员。类的静态函数只能调用静态成员,因为静态函数不包含this指针。静态数据成员被类的所有对象所共享,包括该类派生类的对象。即派生类对象与基类对象共享基类的静态数据成员。示例代码如下:class base(public:static int _num;声明静态成员;int base:_num=O;/静态数据成员的真正定义class derived:public base(;main()(base a;derived b;a._num+;coutnbase class static data number num isna._numendl;b._num+;cout*de rived class static data number _num isH b ._numendl;)上面代码运行的结果如下:1、2由此可见派生类和基类共用了一个静态成员。类的静态成员可以成为成员函数的可选参数,而普通成员则不可以。示例代码如下:class base(public:static int _staticVar;int _var;void fool(int i=_staticVar);/正确,_staticVar 为静态数据成员void foo2(int i=_var);/错误,为普通数据成员)类的静态成员的类型可以是所属类的类型,而普通成员则不可以。普通成员的只能声明为所属类类型的指针或引用 示例代码如下:class base(public:static base _objectl;正确,静态数据成员 107 第2篇 C/C+基础知识base _object2;错误base*pObject;/正确,指针base&mObject;/正确,引用【答案】静态成员可以独立访问,不需要创建类的实例,它也不能用实例来进行调用。类的静态方法只能访问类的静态成员。9.4多 态多态是面向对象编程语言的3要素之一。多态允许将子类类型的指针复制给父类类型的指针,多态性在C+中是通过虚函数来实现的。C语言由于是面向过程语言,所以它不支持多态,但是可以通过结构来进行一些类似的模拟。面试题1 0 3 什么是多态?多态的作用【出现频率】【关键考点】多态的概念;多态的作用。【考题分析】多态是面向对象的重要特性之一,它是一种行为的封装,简单的描述就是“一个接口,多种实现”,也就是同一种事物所表现出的多种形态。编写程序实际上就是一个将世界的具体事物进行抽象化的过程,多态就是抽象化的一种体现,把一系列具体事物的共同点抽象出来,再通过这个抽象的事物,与不同的具体事物进行对话。对不同类的对象发出相同的消息的时候,将会有不同的行为。例如,你的老板让所有员工在9点钟开始工作。他会在9点钟的时候发公开消息说:“开始工作”即可,而不需要对销售人员说:“开始销售工作”,对技术人员说:“开始技术工作”。因 为“员工”是一个抽象的事物,只要是员工就可以开始工作,他知道这一点就行了。至于每个员工,当然会各司其职,做各自的工作。在面向对象编程中多态的主要作用表现为以下两点:(1)应用程序可以不必为每一个派生类编写功能调用,而只需要对抽象基类进行处理即可。这样就大大提高程序的可复用性,精简了代码的编写量。尽量多的编写可复用代码是编写好面向对象语言程序的一个重要规则。(2)派生类的功能可以被基类的方法或引用变量所调用,这称作向后兼容,可以在很大程度上提高可扩充性和可维护性。多态的使用示例代码如下:108 第9章 面向对象与类class Bird/定义抽象类public:virtual void fly()/定义虚函数(cout ”Bird can fly endl;class Duck:public Bird(public:void fly(cout Duck cant fly1 )class Chicken:public Bird(public:void fly(cout Chicken can*t flyH)void main()(Bird*birdOne=new Duck();子类继承抽象类/继承,派生类1endl;/继承,派生类2fly();Bird*birdTwo=new Chicken();birdTwo-fly();Bird birdThree;birdThree.fly();上面代码定义了一个抽象类Bird和 Bird的两种子类Duck和 Chicken,它们都有一个fly 的方法。子类的fly 方法是派生于父类的虚函数的,两个子类的方法表现出不同的功能,运行结果如下:Duck cant flyChicken can*t flyBird can fly【答案】多态是面向对象编程的核心概念之一。多态技术允许将父类设置成和它的一个或更多的子对象相等。面试题1 0 4 在 C+中如何实现多态【出现频率】【关键考点】C+中多态的实现【考题分析】在 C+中,编程者经常指的多态是动态多态,它的实现的基础是继承机制和虚函数,通过抽象类的派生来实现多态。实现动态多态的示例代码如下:109 第2篇C/C+基础知识/dynamic_poly.h#include class Vehicle 定义抽象类(public:virtual void run()const=0;)class Car:public Vehicle/派生于 Vehicle 的具体类 Car(public:virtual void run()const(std:cout run a carn;)class Airplane:public Vehicle/派生于 Vehicle 的具体类 Airplane(public:virtual void run()conststd:cout run a airplanenn;)#include#include#include Hdynamic_poly.h/通过指针run任何vehiclevoid run_vehicle(const Vehicle*vehicle)vehicle-run();)int main()(Car car;Airplane airplane;run_vehicle(&car);run_vehicle(&airplane);/根据vehicle的具体类型调用对应的run()/调用 Car:run()/调用 Airplane:run()上面代码展示了动态多态的实现,通过定义抽象基类定义派生类方法的虚函数,客户程序可以通过指向基类Vehicle的指针来使用具体对象。并且可以通过继承将抽象类的虚函数定义的公共方法具体实现。上面代码中Airpalne和 Car都是派生于V ehide,它们都有run()的方法,并且功能有所不同。另外C+的多态还有静态多态、函数多态以及编程者比较少见的宏多态,静态多态通过彼此单独定义但支持共同操作的具体类来描述共同性,也就是说,必须存在必需的同名成员函数。静态多态的示例代码如下:#include class Car/具体类 Car(public:void run()const(std:cout run a carnu;)110 第9章 面向对象与类class Airplane/具体类 Airplane(public:void run()conststd:cout *run a airplanenn;);#include#include#includetemplatevoid runHstatic_poly.hnvehicle(const Vehicles vehicle)(vehicle.run();/根据vehicle的具体类型调用对应的run()/通过引用而run任何vehicleint main()(Car car;Airplane airplane;run_vehicle(car);run_vehicle(airplane);/调用 Car:run()/调用 Airplane:run()上面代码中,Vehicle被修改后用作模板参数而不是公共基类对象,通过编译器进行处理以后,最终得到run_vehicle()和 run_vehicle()这两个不同的函数,这是和动态多态不同的。静态多态为C+引入了泛型的概念。这是面向对象编程的一个重要概念,泛型编程被认为是“组件功能基于框架整体而设计”的模板编程。例如,STL就是泛型编程的典范之-o STL是一个框架,它可以提供大量的算法、容器和迭代器,而且全部以模板技术实现。函数多态也就是编程者经常说的重载,基于不同的函数参数列表,相同名称的函数可以指向不同的函数定义。函数多态的示例代码如下:#include#include int my_add(int a,int b)return a+b;int my_add(int a,std:string b)(return a+atoi(b.c_str();)int main()(int i=my_add(1,2);int s=my_add(1,2);std:cout ni=i unn;/定义两个重载的函数/两个整数相加/一个整数和一个字符串相加std:cout s=s n;经过重载,相同名称的函数就变成了不同的函数。他们可以有不同的参数列表,并且有不同的返回值。带变量的宏可以实现一种初级形式的静态多态,这就是宏多态。宏多态 111 第2篇C/C+基础知识的示例代码如下:#include#include#define ADD(A,B)(A)+(B);定义泛化记号:宏 ADDint main()|int il(1),i2(2);std:string si(Hello,),s2(world!);int i=ADD(il,i2);/两个整数相加std:string s=ADD(si,s2);/两个字符串“相加”std:cout ni=i nn;std:cout s=s n;上面代码在被编译器编译时,表达式ADD(il,i2)和 ADD(sl,s2)分别被替换为两个整数相加和两个字符串相加的具体表达式。整数相加也就是位求和,而字符串相加则是数据串进行连接。运行的结果如下:1 +2=3Hello,+world!=Hello,world!【答案】多态有动态多态、静态多态、函数多态和宏多态等。编程者常说的多态指的是动态多态,它是基于继承机制和虚函数来实现的。112