|
|
|
|
移动端

1.16.3 继承(2)

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

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

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


1.16.3  继承(2)

【真题 260】有如下代码:

  1. #include<iostream.h> 
  2. class CBase  
  3. {  
  4. public:  
  5. CBase(){ cout <<"constructing CBase class"<< endl; }  
  6. ~CBase(){ cout <<"destructing CBase class"<< endl; }  
  7. };  
  8. class CSub : public CBase  
  9. {  
  10. public:  
  11. CSub(){ cout <<"constructing CSub class"<< endl; }  
  12. ~CSub(){ cout <<"destructing CSub class"<< endl; }  
  13. };  
  14. void main()  
  15. {  
  16. CSub obj;  

程序的输出为()。

A.constructing CSub class constructing CBase class destructing CSub class destructing CBase class

B.constructing CBase class constructing CSub class destructing CBase class destructing CSub class

C.constructing CBase class constructing CSub class destructing CSub class destructing CBase class

D.constructing CSub class constructing CBase class destructing CBase class destructing CSub class 答案:C。

在继承中,当子类构造一个对象时,首先,要调用父类的构造函数,然后,子类调用自己的构造函数,此时完成子类的对象构造。而在执行析构函数时,顺序正好相反,首先释放子类的资源,然后再释放父类的资源。本题中,首先输出 constructing CBase class,然后输出 constructing CSub class,紧接着输出 destructing CSub class,最后输出 destructing CBase class。所以,选项 C正确。

【真题 261】有如下代码:

  1. class ClassA  
  2. {  
  3. public:  
  4. virtual ~ClassA(){};  
  5. virtual void FunctionA(){};  
  6. };  
  7. class ClassB  
  8. {  
  9. public:  
  10. virtual void FunctionB(){};  
  11. };  
  12. class ClassC : public ClassA, public ClassB  
  13. {  
  14. public:  
  15. };  
  16. ClassC aObject;  
  17. ClassA* pA = &aObject;  
  18. ClassB* pB = &aObject;  
  19. ClassC* pC = &aObject; 

下面关于 pA,pB,pC的取值描述中,正确的是()。

A.pA,pB,pC的取值相同 B.pC=pA+pB

C.pA和 pB不相同 D.pC不等于 pA也不等于 pB

答案:C。

本题中,ClassA* pA=&aObject;

ClassB* pB=&aObject;
ClassC* pC=&aObject;

这三行代码实际等价于:

  1. ClassA* pA=static_cast<ClassA*>(&aObject);  
  2. ClassB* pB=static_cast<ClassB*>(&aObject);  
  3. ClassC* pC=&aObject; 

假设 ClassA的内存地址块是 1,ClassB的内存地址块是 2,则 ClassC的内存包含了 1和 2,而取地址操作通常指的是取首地址,即 pA指向 ClassA的首地址, pB就指向了 ClassB的首地址,由于 ClassC采用的是多继承的方式,在继承 ClassB后,pC指向的首地址与 pA一样。

通过上面分析可知, pA与 pC取值相同, pA与 pB取值不相同。因此,选项 C正确,选项 A、选项 B与选项 D错误。所以,本题的答案为 C。

【真题 262】采用上一题中的代码,定义了 ClassA* pA2,下面代码中正确的是()。

A.pA2=static_cast<ClassA*>(pB);

B.void*pVoid=static_cast<void*>(pB); pA2=static_cast<ClassA*>(pVoid);

C.pA2=pB;

D.pA2=static_cast<ClassA*>(static_cast<ClassC*>(pB));答案: D。 C++标准中有四个类型转换符: static_cast、dynamic_cast、reinterpret_cast和 const_cast。其中, static_cast

的用法为:static_cast < type-id > ( expression ) 该运算符把 expression转换为 type-id类型,但没有运行时类型检查来保证转换的安全性。 static_cast主要有如下几种用法:

1)用于类层次结构中基类和子类之间指针或引用的转换。把子类的指针或引用转换成基类表示是安全的,但把基类指针或引用转换成子类指针或引用时,由于没有动态类型检查,所以,它是不安全的,基类和子类之间的动态类型转换建议使用 dynamic_cast。

2)用于基本数据类型(例如 enum、struct、int、char和 float等)之间的转换,例如把 int转换成 char,把 int转换成 enum。这种转换的安全性也要开发人员来保证。

3)把 void指针转换成目弊钹型的指针。

4)把任何类型的表达式转换成 void类型。

需要注意的是, static_cast不能转换掉 expression的 const、volitale或者_unaligned属性。以如下代码为例:

  1. int n = 6;  
  2. double d = static_cast<double>(n); // 基本类型转换  
  3. int *pn = &n;  
  4. double *d = static_cast<double *>(&n); //无关类型指针转换,编译错误  
  5. void *p = static_cast<void *>(pn); //任意类型转换成void 类型 

本题中,对于选项 A,static_cast用于子类与基类指针或引用的转换,由于 pA2与 pB不存在继承关系,因此,不能用 static_cast来转换,所以,选项 A错误,同理,选项 C也是错误的。对于选项 B,void*指针与对象指针的转换是不安全的,转换的结果可能是错误的,因此,选项 B错误。

对于选项 D,虽然把基类指针转换为子类指针是不安全的,在这道题中 pB本来就是指向 ClassC的指针,因此首先把 pB转为指向 ClassC的指针是成功的,接着再把这个指向 ClassC的指针转换为指向 ClassA的指针也是成功的,因为 ClassA是 ClassC的基类,把子类的指针转换为基类的指针是安全的,所以,选项 D正确。

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

51CTO读书频道二维码


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

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

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

读 书 +更多

Linux服务器安全策略详解

Linux主要用于架设网络服务器。如今关于服务器和网站被黑客攻击的报告几乎每天都可以见到,而且随着网络应用的丰富多样,攻击的形式和方法...

订阅51CTO邮刊

点击这里查看样刊

订阅51CTO邮刊