|
|
|
|
移动端

1.16.2 构造函数与析构函数(2)

《程序员面试笔试真题与解析》本书针对当前各大 IT企业面试笔试中特性与侧重点,精心挑选了 3年以来近百家典型 IT企业的面试笔试真题,这些企业涉及业务包括系统软件、搜索引擎、电子商务、手机 APP、安全关键软件等,面试笔试真题非常具有代表性与参考性。本节为大家介绍构造函数与析构函数。

作者:猿媛之家来源:机械工业出版社|2017-12-06 18:43

年前最后一场技术盛宴 | 1月27日与京东、日志易技术大咖畅聊智能化运维发展趋势!


1.16.2 构造函数与析构函数(2)

【真题 252】如果 MyClass为一个类,那么当执行“ MyClass a[5], *b[6]”语句时,会自动调用该类

构造函数的次数是( )次。

A.2  B.5  C.4  D.9

答案:B。

由于题目中 a[5]是一个 MyClass对象数组,它定义了 5个 MyClass对象,所以,每个 MyClass对象都会调用 MyClass的构造函数一次,合计 5次。而*b[6]是一个指针变量数组,它定义了 6个对象指针,而这 6个对象指针并不会进行实例化对象,因此,不会调用构造函数,调用 MyClass构造函数的次数为 0次。所以,二者加起来的次数仍然为 5次。

那么,问题来了,为什么指针变量不调用构造函数呢?其实,指针变量也可以被看作对象,只是在本题中,它的类型是 MyClass *,它如果要调用构造函数,也只是类 MyClass *的构造函数,而不会是 MyClass类的构造函数。由于指针类型是基本的数据类型,跟 int、char等属于同一类,而众所周知,基本数据类型是没有构造函数的,例如, int i语句定义了一个 int类型的变量 i,但它不会调用 int类型的构造函数,因为没有这个构造函数。所以,指针变量也是,不会有如 int *的构造函数。

为了更加具有说服力,请看如下代码:

  1. #include<iostream> 
  2. using namespace std;  
  3. unsigned int cnt = 0;  
  4. class MyClass  
  5. {  
  6. public:  
  7. MyClass()  
  8. {  
  9. cout <<"Call constructor! "<< (++cnt) << endl;  
  10. }  
  11. };  
  12. int main()  
  13. {  
  14. MyClass a[5], *b[6];  
  15. return 0;  

程序输出如下:

  1. Call constructor! 1  
  2. Call constructor! 2  
  3. Call constructor! 3  
  4. Call constructor! 4  
  5. Call constructor! 5 

所以,本题的答案为 B。

引申:假定 MyClass为一个类,那么在执行 MyClass a, b(2),*p;语句时,自动调用该类的构造函数几次?

C++语言在创建一个对象时,会调用类的构造函数。本题中,当定义 a时,会调用 MyClass的默认构造函数。定义 b时,会调用 MyClass的有一个参数的构造函数。创建指针 p时,由于 p本身不是对象,所以,此时不会调用类的构造函数。

【真题 253】有如下程序,执行后的输出结果是()。

  1. #include<iostream> 
  2. using namespace std;  
  3. class BASE  
  4. {  
  5. public:  
  6. ~BASE()  
  7. {  
  8. cout << "BASE";  
  9. };  
  10. };  
  11. class DERIVED :public BASE  
  12. {  
  13. public:  
  14. ~DERIVED()  
  15. {  
  16. cout << "DERIVED";  
  17. };  
  18. };  
  19. int main()  
  20. {  
  21. DERIVED x;  
  22. return 0;  

A.BASE B.DERIVED C.BASEDERIVED  D.DERIVEDBASE答案:D。析构函数的作用与构造函数正好相反,是在撤销对象时由系统自动调用的。在程序的执行过程中,

当遇到某一对象的生存期结束时,系统会自动调用该对象的析构函数,然后再收回为对象分配的存储空间,即要撤销一个对象。通常情况下, main函数结束时会调用各个对象的析构函数,先调用派生类的析构函数,再调用基类的析构函数,这个过程与构造函数的调用次序相反。根据以上的分析可知,选项 D正确。

【真题 254】什么时候调用析构函数与构造函数?

构造函数是一种特殊的函数,主要用来在创建对象时初始化对象,即为对象成员变量赋初始值。它的作用是保证每个对象的数据成员都有合适的初始值。析构函数与构造函数相反,作用是回收内存和资源,当对象脱离其作用域时(例如对象所在的函数已调用完毕),系统会自动执行析构函数。析构函数往往用来做“清理善后”的工作(例如在建立对象时用 new开辟了一片内存空间,应在退出前在析构函数中用 delete释放),用于释放在构造函数或对象生命期内获取的资源。

事实上,构造函数和析构函数都是由编译器隐式调用的,而不需要程序员自己编写程序。函数的调用顺序取决于程序的执行进入和离开实例化对象时所在的那个作用域的顺序。一般构造和析构的次序是相反的:构造的过程从类层次的最根处开始,在每一层中,首先调用基类的构造函数,然后调用成员对象的构造函数。析构则严格按照与构造相反的次序执行,该次序是唯一的,否则编译器将无法自动执行析构过程。

【真题 255】 C++语言将父类的析构函数定义为虚函数,下列关于此说法的描述中,正确的是()。

A.释放父类指针时能正确释放子类对象 B.释放子类指针时能正确释放父类对象

C.这样做是错误的 D.以上全错答案:A。析构函数是一种特殊的成员函数,它没有返回值,也不需要用户调用,它在销毁对象时自动执行。

与构造函数不同的是,析构函数的名字是在类名前面加一个“~”符号。需要注意的是,由于析构函数没有参数,也不能被重载,因此,一个类中,只能存在一个析构函数。如果用户没有定义析构函数,那么编译器会自动生成析构函数。

在 C++语言中,多态的表现形式通常是使用父类的指针指向子类的对象,如果把析构函数定义为虚函数,当释放父类指针时,也会释放子类的对象。如果不使用虚函数的话,父类的指针即使指向子类的对象,也只能够释放父类的对象了。所以,选项 A正确。

【真题 256】以下关于拷贝构造函数的描述中,正确的是()。

A.拷贝构造函数的函数名同类名,也是一种构造函数,该函数返回自身引用

B.拷贝构造函数只有一个参数,必须是对某个对象的引用

C.每个类都必须有一个拷贝初始化构造函数,如果类中没有说明拷贝构造函数,则编译器会自动生成一个缺省拷贝构造函数,作为该类的保护成员

D.拷贝初始化构造函数的作用是将一个已知对象的数据成员值拷贝给正在创建的另一个同类的对象

答案:B、D。

拷贝构造函数又称复制构造函数,是一种特殊的构造函数,它由编译器调用来完成一些基于同一类的其他对象的构建及初始化。其唯一的形参必须是引用,但并不限制为 const,一般会加上 const限制。此函数经常用在函数调用时用户定义类型的值传递及返回。拷贝构造函数要调用基类的拷贝构造函数和成员函数。如果可以的话,它将用常量方式调用,另外,也可以用非常量方式调用。

在 C++语言中,下面三种对象需要调用拷贝构造函数:

1)一个对象作为函数参数,以值传递的方式传入函数体。

2)一个对象作为函数返回值,以值传递的方式从函数返回。

3)一个对象用于给另外一个对象进行初始化(通常称为赋值初始化)。

在前两种情况不使用拷贝构造函数的时候,会导致一个指针指向已经被删除的内存空间。对于第三种情况,初始化和赋值的不同含义是拷贝构造函数调用的原因。事实上,拷贝构造函数是由普通构造函数和赋值操作符共同实现的。描述拷贝构造函数和赋值运算符的异同的参考资料有很多,在此不再赘述,有兴趣的读者可以自行搜索资料学习。

拷贝构造函数的使用原则如下:

①对于包含动态分配成员或包含指针成员的类都应该提供拷贝构造函数。

②在提供拷贝构造函数的同时,还应该考虑重载赋值操作符“ =”。

拷贝构造函数必须以引用的形式传递(参数为引用值)。其原因如下:当一个对象以值传递的方式传一个函数的时候,需要把形参的对象构造生成一个临时对象赋值给实参。这个过程就需要调用拷贝构造函数。而拷贝构造函数被调用的时候又需要进行值传递,又需要调用拷贝构造函数,以此类推会无限地调用,这会导致无限循环直至栈溢出( Stack Overflow)。因此参数必须是对象的引用。

所以,选项 B与选项 D正确。因此,本题的答案为 B、D。

【真题 257】下列关于构造方法的描述中,正确的是()。

A.类中的构造方法不可省略  B.构造方法必须与类同名,但方法不能与类同名

C.构造方法在一个对象被 new时执行  D.一个类只能定义一个构造方法

答案:C。

喜欢的朋友可以添加我们的微信账号:

51CTO读书频道二维码


51CTO读书频道活动讨论群:365934973

【责任编辑:book TEL:(010)68476606】

回书目   上一节   下一节
点赞 0
分享:
大家都在看
猜你喜欢

读 书 +更多

网管第一课——网络组建与管理

本书针对初级网管朋友所需掌握的网络组建和网络管理技能,以示例方式编写而成,其主要特点就是实用性和可操作性非常强。 全书共分8章,分...

订阅51CTO邮刊

点击这里查看样刊

订阅51CTO邮刊