是实参变量的副本;如果传递的是对象,还将调用拷贝构造函数。因此,当参数传递的数据较大时,用引用比用一般变量传递参数的效率和所占空间都好。
(3)使用指针作为函数的参数虽然也能达到与使用引用的效果,但是,在被调函数中同样要给形参分配存储单元,且需要重复使用\指针变量名\的形式进行运算,这很容易产生错误且程序的阅读性较差;另一方面,在主调函数的调用点处,必须用变量的地址作为实参。而引用更容易使用,更清晰。
134. 什么时候需要“引用”:
流操作符(<<、>>)和赋值操作符(=)的返回值、拷贝构造函数的参数、赋值操作符的参数、其它情况都推荐使用引用。
50. 在什么时候需要使用“常引用”:
如果既要利用引用提高程序的效率,又要保护传递给函数的数据不在函数中被改变,就应使用常引用。
51. 引用与指针有什么区别:
1) 引用必须被初始化,指针不必。
2) 引用初始化以后不能被改变,指针可以改变所指的对象。 3) 不存在指向空值的引用,但是存在指向空值的指针。
28. 描述内存分配方式以及它们的区别?
1)从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整 个运行期间都存在。例如全局变量,static变量。
2)在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数
执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集。 3) 从堆上分配,亦称动态内存分配。程序在运行的时候用malloc或new申请任意多少
的内存,程序员自己负责在何时用free或delete释放内存。动态内存的生存期由
程序员决定,使用非常灵活,但问题也最多。
41. 解释堆和栈的区别:
栈:由编译器自动分配释放,存放函数的参数值,局部变量的值等。
堆: 一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收。
54. 全局变量和局部变量在内存中是否有区别?如果有,是什么区别? 答: 全局变量储存在静态数据区,局部变量在堆栈中。
63. 简述数组与指针的区别?
数组要么在静态存储区被创建(如全局数组),要么在栈上被创建。指针可以随时指向任意类型的内存块。 (1)修改内容上的区别 char a[] = “hello”;
a[0] = ‘X’;
char *p = “world”; // 注意p 指向常量字符串
p[0] = ‘X’; // 编译器不能发现该错误,运行时错误
(2) 用运算符sizeof可以计算出数组的容量(字节数)。sizeof(p),p为指针得到的是一个指针变量的字节数,而不是p所指的内存容量。
83. 什么是指针?谈谈你对指针的理解? 指针是一个变量,该变量专门存放内存地址;
指针变量的类型取决于其指向的数据类型,在所指数据类型前加* 指针变量的特点是它可以访问所指向的内存。
127.类成员函数的重载、覆盖和隐藏区别: 成员函数被重载的特征:
(1)相同的范围(在同一个类中); (2)函数名字相同;
(3)参数不同;
(4)virtual 关键字可有可无。
覆盖是指派生类函数覆盖基类函数,特征是: (1)不同的范围(分别位于派生类与基类); (2)函数名字相同; (3)参数相同;
(4)基类函数必须有virtual 关键字。
“隐藏”是指派生类的函数屏蔽了与其同名的基类函数,规则如下:
(1)如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual关键字,基类的函数将被隐藏(注意别与重载混淆)。 (2)如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual 关键字。此时,基类的函数被隐藏(注意别与覆盖混淆)
49. 重载(overload)和重写(overried,有的书也叫做“覆盖”)的区别? 常考的题目。从定义上来说:
重载:是指允许存在多个同名函数,而这些函数的参数表不同(或许参数个数不同,或许参数类型不同,或许两者都不同)。
重写:是指子类重新定义父类虚函数的方法。
从实现原理上来说:
重载:编译器根据函数不同的参数表,对同名函数的名称做修饰,然后这些同名函数就成了不同的函数(至少对于编译器来说是这样的)。如,有两个同名函数:function func(p:integer):integer;和function func(p:string):integer;。那么编译器做过修饰后的函数名称可能是这样的:int_func、str_func。对于这两个函数的调用,在编译器间就已经确定了,是静态的。也就是说,它们的地址在编译期就绑定了(早绑定),因此,重载和多态无关!
重写:和多态真正相关。当子类重新定义了父类的虚函数后,父类指针根据赋给它的不同的子类指针,动态的调用属于子类的该函数,这样的函数调用在编译期间是无法确定的(调用的子类的虚函数的地址无法给出)。因此,这样的函数地址是在运行期绑定的(晚绑定)。
30. 函数重载是什么意思?它与虚函数的概念有什么区别? 函数重载是一个同名函数完成不同的功能,编译系统在编译阶段通过函数参数个数、参数类型不同,函数的返回值来区分该调用哪一个函数,即实现的是静态的多态性。但是记住:不
能仅仅通过函数返回值不同来实现函数重载。
而虚函数实现的是在基类中通过使用关键字virtual来申明一个函数为虚函数,含义就是该函数的功能可能在将来的派生类中定义或者在基类的基础之上进行扩展,系统只能在运行阶段才能动态决定该调用哪一个函数,所以实现的是动态的多态性。它体现的是一个纵向的概念,也即在基类和派生类间实现。
29. 父类写了一个virtual 函数,如果子类覆盖它的函数不加virtual ,能否实现多态? 答:1.virtual修饰符会被隐形继承的。
2.virtual可加可不加,子类覆盖它的函数不加virtual ,也能实现多态。
48.面向对象的三个基本特征,并简单叙述之?
1. 封装:将客观事物抽象成类,每个类对自身的数据和方法实行protection(private, protected,public)
2. 继承:广义的继承有三种实现形式:实现继承(指使用基类的属性和方法而无需额外编码的能力)、可视继承(子窗体使用父窗体的外观和实现代码)、接口继承(仅使用属性和方法,实现滞后到子类实现)。前两种(类继承)和后一种(对象组合=>接口继承以及纯虚函数)构成了功能复用的两种方式。
3. 多态:是将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。简单的说,就是一句话:允许将子类类型的指针赋值给父类类型的指针。
40. 继承优缺点。 优点:
1、类继承是在编译时刻静态定义的,且可直接使用 2、类继承可以较方便地改变父类的实现。
缺点:
1、因为继承在编译时刻就定义了,所以无法在运行时刻改变从父类继承的实现
2、父类通常至少定义了子类的部分行为,父类的任何改变都可能影响子类的行为
3、如果继承下来的实现不适合解决新的问题,则父类必须重写或被其他更适合的类替换。这种依赖关系限制了灵活性并最终限制了复用性。
48. 请说出类中private,protect,public三种访问限制类型的区别:
private是私有类型,只有本类中的成员函数访问;protect是保护型的,本类和继承类可以访问;public是公有类型,任何类都可以访问.
62. 当一个类A 中没有声明任何成员变量与成员函数,这时sizeof(A)的值是多少,请解释一下编译器为什么没有让它为零。
答案:为1。举个反例,如果是零的话,声明一个class A[10]对象数组,而每一个对象占用的空间是零,这时就没办法区分A[0],A[1]?了。
1. 面向对象的程序设计思想是什么?
答:把数据结构和对数据结构进行操作的方法封装形成一个个的对象。
2. 什么是类?
答:把一些具有共性的对象归类后形成一个集合,也就是所谓的类。
3. 对象都具有的二方面特征是什么?分别是什么含义? 答:对象都具有的特征是:静态特征和动态特征。
静态特征是指能描述对象的一些属性,动态特征是指对象表现出来的行为
4. 在头文件中进行类的声明,在对应的实现文件中进行类的定义有什么意义?
答:这样可以提高编译效率,因为分开的话只需要编译一次生成对应的.obj文件后,再次应用该类的地方,这个类就不会被再次编译,从而大大提高了效率。
5. 在类的内部定义成员函数的函数体,这种函数会具备那种属性?
答:这种函数会自动为内联函数,这种函数在函数调用的地方在编译阶段都会进行代码替换。
6. 成员函数通过什么来区分不同对象的成员数据?为什么它能够区分? 答:通过this指针来区分的, 因为它指向的是对象的首地址。
7. C++编译器自动为类产生的四个缺省函数是什么?
答:默认构造函数,拷贝构造函数,析构函数,赋值函数。
8. 拷贝构造函数在哪几种情况下会被调用?
答:1.当类的一个对象去初始化该类的另一个对象时;
2.如果函数的形参是类的对象,调用函数进行形参和实参结合时; 3.如果函数的返回值是类对象,函数调用完成返回时。
9. 构造函数与普通函数在形式上有什么不同?(用构造函数的作用及声明形式来分析) 答:构造函数是类的一种特殊成员函数,一般情况下,它是专门用来初始化对象成员变量的。 构造函数的名字必须与类名相同,它不具有任何类型,不返回任何值。
10. 什么时候必须重写拷贝构造函数?
答:当构造函数涉及到动态存储分配空间时,要自己写拷贝构造函数,并且要深拷贝。
11. 构造函数的调用顺序是什么? 答:1.先调用基类构造函数
2.按声明顺序初始化数据成员
3.最后调用自己的构造函数。
12. 哪几种情况必须用到初始化成员列表?
答:1.类的成员是常量成员初始化;
2.类的成员是对象成员初始化,而该对象没有无参构造函数; 3.类的成员为引用时。
15. 在类外有什么办法可以访问类的非公有成员? 答:友元,继承,公有成员函数。
16. 什么叫抽象类?
答:不用来定义对象而只作为一种基本类型用作继承的类。
17. 运算符重载的意义?
答:为了对用户自定义数据类型的数据的操作与内定义的数据类型的数据的操作形式一致。
18. 不允许重载的5个运算符是哪些? 答:
1. .*(成员指针访问运算符号) 2. ::域运算符
3. sizeof 长度运算符号 4. ?:条件运算符号 5. .(成员访问符)
19. 运算符重载的三种方式?
答:普通函数,友元函数,类成员函数。
20. 流运算符为什么不能通过类的成员函数重载?一般怎么解决? 答:因为通过类的成员函数重载必须是运算符的第一个是自己,而对流运算的重载要求第一个参数是流对象。一般通过友元来解决。
21. 赋值运算符和拷贝构造函数的区别与联系? 答:相同点:都是将一个对象copy到另一个中去。 不同点:拷贝构造函数涉及到要新建立一个对象。
22. 在哪种情况下要调用该类的析构函数? 答:对象生命周期结束时。
24. 友元关系有什么特性?
答:单向的,非传递的,不能继承的。
25. 对对象成员进行初始化的次序是什么?
答:它的次序完全不受它们在初始化表中次序的影响,只有成员对象在类中声明的次序来决定的。
26. 类和对象之间的关系是什么? 答:类是对象的抽象,对象是类的实例。
27. 对类的成员的访问属性有什么? 答:public,protected,private。
31. 构造函数和析构函数是否可以被重载,为什么? 答:构造函数可以被重载,析构函数不可以被重载。因为构造函数可以有多个且可以带参数,而析构函数只能有一个,且不能带参数。