C经典笔试题附答案Word下载.doc

上传人:b****1 文档编号:13160571 上传时间:2022-10-07 格式:DOC 页数:22 大小:232KB
下载 相关 举报
C经典笔试题附答案Word下载.doc_第1页
第1页 / 共22页
C经典笔试题附答案Word下载.doc_第2页
第2页 / 共22页
C经典笔试题附答案Word下载.doc_第3页
第3页 / 共22页
C经典笔试题附答案Word下载.doc_第4页
第4页 / 共22页
C经典笔试题附答案Word下载.doc_第5页
第5页 / 共22页
点击查看更多>>
下载资源
资源描述

C经典笔试题附答案Word下载.doc

《C经典笔试题附答案Word下载.doc》由会员分享,可在线阅读,更多相关《C经典笔试题附答案Word下载.doc(22页珍藏版)》请在冰豆网上搜索。

C经典笔试题附答案Word下载.doc

//加成员名限定A:

:

但更好的办法是在类C中也定义一个同名print函数,根据需要调用A:

print()还是B:

print(),从而实现对基类同名函数的隐藏

9:

下列公共基类导致的二义性如何解决?

classA{ //公共基类

//public成员列表

voidprint(){

cout<

"

thisisxinA:

<

classB:

publicA{};

classC:

classD:

publicB,publicC{};

voidmain(){

Dd;

//声明一个D类对象d

A*pa=(A*)&

d;

//上行转换产生二义性

d.print();

//print()具有二义性,系统不知道是调用B类的还是C类的print()函数

注意:

把子类的指针或引用转换成基类指针或引用是上行转换,把基类指针或引用转换成子类指针或引用是下行转换。

1)main函数中语句“d.print();

”编译错误,可改为以下的一种:

d.B:

print();

d.C:

若改为“d.A:

”又会如何呢?

由于d对象中有两个A类对象,故编译会报“基类A不明确”。

2)语句“A*pa=(A*)&

”产生的二义性是由于d中含有两个基类对象A,隐式 转换时不知道让pa指向哪个子对象,从而出错。

可改为以下的一种:

A*pa=(A*)(B*)&

//上行转换

A*pa=(A*)(C*)&

//上行转换

事实上,使用关键字virtual将共同基类A声明为虚基类,可有效解决上述 问题。

10:

下面哪种情况下,B不能隐式转换为A( )?

(2011•腾讯)

A.classB:

publicA{} B.classA:

publicB{}

C.classB{operatorA();

} D.classA{A(constB&

);

B。

因为子类包含了父类部分,所以子类可以转换为父类,但是相反, 父类没有子类额外定义的部分,所以不能转换为子类,故A正确,而B错误。

非C++内建型别A和B,在以下几种情况下B能隐式转化为A。

1)B公有继承自A,可以是间接继承的。

classB:

publicA{

此时若有“Aa;

Bb;

”,则“a=b;

”合法。

2)B中有类型转换函数。

classB{

operatorA();

”,则“a=b;

3)A实现了非explicit的参数为B(可以有其他带默认值的参数)的构造函 数

classA{

A(constB&

11:

调用一成员函数时,使用动态联编的情况是()。

(2011•淘宝)

A.通过对象调用一虚函数 B.通过指针或引用调用一虚函数

C.通过对象调用静态函数 D.通过指针或引用调用一静态函数

结合一段示例代码来看虚函数的作用,以帮助大家理解多态的意义所在。

例2:

下述代码的输出结果是什么?

classbase{

virtualvoiddisp(){cout<

hello,base1"

}voiddisp2(){cout<

hello,base2"

endl;

classchild1:

publicbase{

voiddisp(){cout<

hello,child1"

}

voiddisp2(){cout<

hello,child2"

base*base=NULL;

child1objchild1;

base=&

objchildl;

base->

disp();

disp2();

输出:

hello,childl

hello,base2

从上述代码可见,通过指针访问函数时:

1)不加virtual时,具体调用哪个版本的函数只取决于指针本身的类型,和指针所指对象的类型无关。

2)而加virtual时,具体调用哪个版本的函数不再取决于指针本身的类型,而是取决于指针所指对象的类型。

13:

构造函数为什么不能为虚函数?

假设有如下代码:

classA{

A(){}

B():

A() {}

};

intmain(){

Bb;

B*pb=&

b;

则构造B类的对象时:

1.根据继承的性质,构造函数执行顺序是:

A()B()

2.根据虚函数的性质,如果A的构造函数为虚函数,且B类也给出了构造函数,则应该只执行B类的构造函数,不再执行A类的构造函数。

这样A就不能构造了。

3.这样1和2就发生了矛盾。

另外,virtual函数是在不同类型的对象产生不同的动作,现在对象还没有产生,如何使用virtual函数来完成你想完成的动作。

14:

哪些函数不能为虚函数?

常见的不能声明为虚函数的有:

普通函数(非成员函数)、静态成员函数、构造函数、友元函数,而内联成员函数、赋值操作符重载函数即使声明为虚函数也无意义。

1)为什么C++不支持普通函数为虚函数?

普通函数(非成员函数)只能被overload(重载),不能被override(覆盖),声明为虚函数也没有什么意义,因此编译器会在编译时绑定函数。

为什么C++不支持构造函数为虚函数?

上例己经给出了答案。

2)为什么C++不支持静态成员函数为虚函数?

静态成员函数对于每个类来说只有一份代码,所有的对象都共享这一份代码, 它不归某个具体对象所有,所以它没有要动态绑定的必要性。

3)为什么C++不支持友元函数为虚函数?

因为C++不支持友元函数的继承,没有实现为虚函数的必要。

以下两种函数被声明为虚函数时,虽然编译器不会报错,但是毫无意义。

内联函数:

内联函数是为了在代码中直接展开,减少函数调用花费的代价,虚函数是为了在继承后,对象能够准确地执行自己的动作,这是不可能统一的。

即使虚函数被声明为内联函数,编译器遇到这种情况根本不会把这样的函数内联展开,而是当作普通函数来处理。

赋值运算符:

虽然可以在基类中将成员函数operator定义为虚函数,但这样做没有意义。

赋值操作符重载函数要求形参与类本身类型相同,故基类中的赋值操作符形参类型为基类类型,即使声明为虚函数,也不能作为子类的赋值操作符。

15:

以下描述正确的是()。

(2011•盛大游戏)

A.虚函数是可以内联的,可以减少函数调用的开销提高效率

B.类里面可以同时存在函数名和参数都一样的虚函数和静态函数

C.父类的析构函数是非虚的,但是子类的析构函数是虚的,delete子类对象指针会调用父类的析构函数

D•以上都不对

C。

C中delete子类对象指针会调用父类的析构函数(即使子类的析构 函数不是虚的,对子类对象指针调用析构函数,也会调用父类的析构函数), 但若delete父类对象指针却不会调用子类的析构函数(因为父类的析构函数 不是虚函数,不执行动态绑定)。

16:

以下代码的输出结果是()。

(2012•小米)

classB{

B(){

cout<

”Bconstructor,”;

s=“B”;

voidf(){cout<

s;

peivate:

strings;

classD:

publicB{

D():

B(){

Dconstructor,"

;

s=“D”;

}private:

intmain(void){

B*b=newD();

b->

f();

((D*)b)->

f();

deleteb;

return0;

输出结果是:

Bconstructor,Dconstructor,BD

若在类B中的函数f前加上virtual关键字,则输出结果为:

Bconstructor,Dconstructor,DD

可见若函数不是虚函数,则不是动态绑定。

17:

下列代码的输出结果是什么?

(2012•网易)

classA{

virtualvoidFun(intnumber=10){

std:

A:

Funwithnumber"

number<

publicA{

virtualvoidFun(intnumber=20){

cout<

”B:

Funwithnumber’’<

A&

a=b;

a.Fun();

B:

Funwithnumber10。

虚函数动态绑定到B,但缺省实参是编译时候 确定的10,而非20。

构造函数和析构函数中的虚函数

构造派生类对象时,首先运行基类构造函数初始化对象的基类部分。

在执行基类构造函数时,对象的派生类部分是未初始化的。

实际上,此时对象还不是一个派生类对象。

撤销派生类对象时,首先撤销它的派生类部分,然后按照与构造顺序的逆序撤销它的基类部分。

在这两种情况下,运行构造函数或析构函数时,对象都是不完整的。

为了适应这种不完整,编译器将对象的类型视为在构造或析构期间发生了变化。

在基类构造函数或析构函数中,将派生类对象当作基类型对象对待。

如果在构造函数或析构函数中调用虚函数,则运行的是为构造函数或析构函数自身类型定义的版本。

18:

以下哪些做法是不正确或者应该极力避免的()。

(多选)(2012•搜狗)

A.构造函数声明为虚函数 B.派生关系中的基类析构函数声明为虚函数

C.构造函数调用虚函数 D.析构函数调用虚函数

ACD。

构造函数和析构函数是特殊的成员函数,在其中访问虚函数时,C++采用静态联编,即在构造函数或析构函数内,即使是使用虚函数名”的形式来调用,编译器仍将其解释为静态联编的“本类名:

虚函数名”,因而这样会与使用者的意图不符,应该尽量避免。

9.2.2虚函数表指针(vptr)及虚基类表指针(bptr)

C++在布局以及存取时间上主要的额外负担是由virtual引起的,包括:

virtual

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 考试认证 > IT认证

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1