重拾C++经典笔试30题(21-30)

简介: 重拾C++经典笔试30题(21-30)

重拾C++经典笔试30题(21-30)

1.       为什么Delete会出错?


class CBase

{

public:

        CBase() { cout <<"CBase" << endl; }

        virtual ~CBase() { cout <<"~CBase" << endl;}

};

classCDerived : public CBase

{

public:

        CDerived() { cout <<"CDerived" << endl; }

        ~CDerived() { cout <<"~CDerived" << endl; }

};

int main()

{

        CBase base;

        CBase* pBase = new CBase;

        pBase = &base;

        delete pBase; //运行时报错!

}



【分析如下】:


1.pBase指向了栈区内存,那是系统管理的空间,不能用delete释放的。


2.程序在堆区new的空间最后没有被释放,造成了内存泄露。


3.最好不要随便把申请到堆区空间的指针指向别处,至少也要有一个指针指向申请的空间。以便最后释放的是自己申请的那块内存。


【修正后做法】:


int main()

{

   CBase base;

   CBase* pBase = new CBase;

   CBase* pBase2 = pBase;   //至少也要有一个指针指向申请的空间

   pBase = &base;

   delete pBase2;  //以便最后释放的是自己申请的那块内存。

} //运行时不再报错!

【再深入点】:程序有两个问题:


1.内存泄露,new出来的没delete;


2.两次析构;base不是new出来,在生命周期结束(也就是你函数结束的时候)会自动释放,你主动调用delete将其析构,系统在函数结束时又会对其析构,所以才会报错。而且报错的地方应该是程序退出时。



2.       类中静态常成员变量的定义?


#include<iostream>

usingnamespace std;

//可以在类的声明中对常量的类变量进行赋值

//VS2008可以,vc6.0不可以。和编译器有关。

class myclass

{

public:

        static const int i=20; //只有类的静态常量数据成员才可以在类中初始化。

};

const int myclass::i = 10;

int main()

{

        cout<<myclass::i<<endl;

        return 0;

}

3.      重载和多态的关系?


不同点


重载overload


覆盖override


1.是否支持多态?


不支持


支持


2.存在形式?


可以在类中或在C++语言中都可以体现


存在于类中父类、子类之间。


3.参数列表、返回值


参数列表或返回值不同,或二者都不同。


参数列表、返回指标必须相同。




4.      输出格式:printf用!


%a(%A)    


浮点数、十六进制数字和p-(P-)记数法(C99)


%c          


字符


%d            


有符号十进制整数


%f            


浮点数(包括float和doulbe)


%e(%E)    


浮点数指数输出[e-(E-)记数法]


%g(%G)    


浮点数不显无意义的零"0"


%i            


有符号十进制整数(与%d相同)


%u            


无符号十进制整数


%o            


八进制整数    e.g.     0123


%x(%X)    


十六进制整数0f(0F)   e.g.   0x1234


%p            


指针


%s            


字符串


 


5.      一个参数或指针可以既是const又是volatile)解读?


Volatile 以防止编译器将其优化成从寄存器中读取。一个定义为volatile的变量时说这个变量可能会被意想不到地改变,这样编译器就不会去假设这个变量的值。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。


一个参数可以既是const又是volatile,const是不让程序修改,volatile是意想不到的改变,不是程序修改。一个指针也可以是volatile,中断服务子程序修改一个指向buffer的指针。


6.      Little Endian低字节序(由低字节—>高字节存储);计算机默认的为低字节序。


High Endian高字节序(由高字节—>低字节存储);


typedef struct bitstruct

{

        int b1:5;

        int b2:2;

        int b3:2;

}bitstruct;

int main()

{

        bitstruct b;

        memcpy(&b,"EMCEXAMINATION",sizeof(b));

        cout << sizeof(b) << endl;

        printf("%d,%d\n",b.b1,b.b2);//5,-2

        return 0;

}

[解读]:1.sizeof(b)=4;即4个字节的大小。


2.memcpy将”EMC …”存入b中。


3.实质b中只有5+2+2,9位。即对应字符也只有”EM”.E的ASCII码为0X45,M的ASCII码为0X4D。


满足高字节—>低字节存储0X4D0X45,对应二进制位:01001101 0100 0101。


4.对应的b1,满足(低字节存放于低位)取得后低地址的5位0 0101,首位为0代表正数,大小为5。


对应的b2,取10,首位为1代表负数,取补码后得到b2=-2。


27.输出结果?


int main()

{

        int a[5][2] = {0,1,2,3,4,5,6,7,8,9};

     

        int *p = a[0];

        int (*p2)[2] = &a[1];

        ++p;

        ++p2;

     

        printf("%d\n",*p); //1 p 是整型指针,初始指向元素0,加1指向1

        printf("%d\n",**p2); //4 p2是含2个元素的数组指针,初始指向元素2,该指针加1是向后移动2个数据,所以指向4

        printf("%d \n",p2[1][2]); //如何解读? 见下解读。

        return 0;

}



0


1


0


0 (p)


1(++p后)


1


2  (P2指向)


3


2


4 (++p2后)


5


3


6  (p2+1后)


7


4


8  (p2[1][2])


9



解读:p2是一个指针,是一个指向包含两个元素数组的指针变量。和普通的指针不同的地方时它指向的长度为2。(*p2)[2]和a是等价的。


对于p2[1][2],此时p2指向4,前一个下标1就是p2指针再加1指向6,后一个下标加2移动2个元素,指向了8。




28.拷贝构造输出结果?


class A

{

   static int objectCount;

public:

   A()

   {

       objectCount++;

       cout << "A():" <<objectCount << endl;

   }

 

   A(const A& r)

   {

       objectCount++;

       cout << "A(const A&r):" << objectCount << endl;

   }

     

   ~A()

   {

       objectCount--;

       cout << "~A():"<< objectCount << endl;

   }

};

intA::objectCount = 0;

A f(A x)        

{

   cout << endl <<  "Begin: f(A x)" << endl;

   return x;   //【临时对象】调用默认拷贝构造函数A(const A& r):3

}                //~A():2

int main()

{

   A h;        //A():1

   A h2 = f(h); //调用默认拷贝构造函数A(constA& r):2

   cout << endl <<"End(main): f(A x)" << endl << endl;

     

   return 0;  

}               //~A():1  析构h2  

//~A():0  构函h

29.四类强制类型转换


类型


示意


举例


static_cast


1.类型转换,编译器隐式执行的任何类型都可由static_cast显示完成;2.使用类型信息执行转换,在转换执行必要的检测(越界检测、类型检查),操作相对安全;


int—>double


int ival;


double result = static_cast<double> ival


const_cast


转换掉对象的const属性


下举例


dynamic_cast


运行时类型检查,用于继承体制下的由上到下的转换downcast。


下举例


reinterpret_cast


1.仅仅重新编译了给定对象的比特模型,而没有进行二进制转换;2.为操作数提供低层次的重新解释。


下举例


举例:


//const_cast 实例.

class B

{

public:

        int m_num;

};

int main()

{

        B b0;

        b0.m_num = 100;

        const B b1 = b0;

        cout << b0.m_num<< " " << b1.m_num << endl;

// 以下修改const对象的值是错误的。

//       b1.m_num = 355;

//       cout << b1.m_num <<endl;  // error C2166: l-value specifiesconst object

//以下使用const_cast是正解.

        const_cast<B&>(b1).m_num =355;

        cout<< b1.m_num << endl;

        return 0;

}

//reinterpret_cast实例

int main()

{

        int n = 9;

        double dval =reinterpret_cast<double& >(n);

        double dval_new =static_cast<double>(n); //成功.

        //[仅仅复制了n的比特位到d,没有进行必要的分析]

        cout << dval << endl;//2.64214e-308

        cout << dval_new << endl;//9

        return 0;

}

//dynamic_cast实例

class B

{

public:

        B() { cout << "B()"<< endl; }

        ~B() { cout << "~B()"<< endl; }

};

class C :public B

{

public:

        C() { cout << "C()"<< endl; }

        ~C() { cout << "~C()"<< endl; }

};

class D :public C

{

public:

        D(){ cout << "D()"<< endl; }

        ~D(){ cout << "~D()"<< endl; }

};

void f(D* pd)

{

        C* pc =dynamic_cast<C*>(pd);   // ok: C isa direct base class

        // pc points to C subobject of pd

        B* pb =dynamic_cast<B*>(pd);   // ok: B isan indirect base class

        // pb points to B subobject of pd    

}

int main()

{

        D objd;

        f(&objd);

        return 0;

}


30. 持续更新中......



30. 如何在C/C++中显示当前程序所在的文件名及行号。


——这个当时没答上来,见过没记住。今天查了下MSDN如下:


__FILE__, //用于显示文件名的宏 %s, 格式如【F:\NeuSoftDemo\NeuSoftDemo.cpp】;__LINE__, //用于显示行号的宏 %d,格式如【12】;


扩展》》__DATE__, //用于显示当前日期,格式如【Sep 18 2012】 %s; __TIME__, //用于显示当前时间,格式如【09:45:01】 %s;


__TIMESTAMP__,//用于显示当前日期和时间,格式如【Tue Sep 18 09:48:07 2012】 %s。


31. 程序纠错题:



[cpp] view plain copy

int main(int argc,char* argv[])

{

char str[5][] = {"First","Second","Thrid","Four","Five"};

char* p[] = {str[4],str[3],str[2],str[1],str[0]};

for(int i = 0; i < 5; i++)

{

printf("%c\n",*(p+i));

}

return 0;

}

int main(int argc, char* argv[])

{

char str[5][] = {"First","Second","Thrid","Four","Five"};

char* p[] = {str[4],str[3],str[2],str[1],str[0]};


for(int i = 0; i < 5; i++)

{

 printf("%c\n",*(p+i));

}

return 0;

}

个人感觉如下:

错误1: char str[5][] 定义出错,需要指定第一维的个数,改为char str[][5]吗?但后面的字符串如"Second"6个字符,还有'\0'。改为:char* str[5]比较稳妥;


错误2: printf("%c\n",*(p+i)); 显然*(p+i) 等价于p[i]存储的是字符串,所以%c应该改为%s。(%c打印的是单个字符,%s打印的是字符串)。


修正后如下:



[cpp]

int main(int argc,char* argv[])

{

char *str[5] = {"First","Second","Thrid","Four","Five"};

char* p[] = {str[4],str[3],str[2],str[1],str[0]};

for(int i = 0; i < 5; i++)

{

printf("%s\n",*(p+i));

}

return 0;

}

33. 递归与非递归实现二分查找。


//非递归实现-


[cpp] view plain copy

void binarySearchUncycle(int nArr[],int nSize,int nSearchVal)

{

int nLow = 0;

int nHigh = nSize-1;

int nMid = 0;

bool bFound = false;

while(nLow <= nHigh)

{

nMid = (nLow + nHigh)/2;

cout << "nMid =" << nMid << endl;

if(nArr[nMid] == nSearchVal)

{

bFound = true;

break;

}

else if(nArr[nMid] > nSearchVal)

{

nHigh = nMid-1;

}

else

{

nLow = nMid+1;

}

}//end while

if(bFound)

{

cout << "The Elem " << nSearchVal << " is Exist in the array!" << endl;

}

else

{

cout << "The Elem " << nSearchVal << " is Not Exist in the array!" << endl;

}

}

[cpp]

//递归实现二分查找

void binarySearchCycle(int nArr[],int low, int high, int nSearchVal)

{

int nLow = low;

int nHigh = high;

int nMid = 0;

bool bFound = false;

nMid = (nLow + nHigh)/2;

if(nArr[nMid] == nSearchVal)

{

bFound = true;

cout << "The Elem " << nSearchVal << " is Exist in the array!" << endl;

return;

}

else if(nArr[nMid] > nSearchVal)

{

nHigh = nMid-1;

binarySearchCycle(nArr,nLow,nHigh,nSearchVal);

}

else

{

nLow = nMid+1;

binarySearchCycle(nArr,nLow,nHigh,nSearchVal);

}

}


相关文章
|
6月前
|
存储 算法 C语言
从C语言到C++_39(C++笔试面试题)next_permutation刷力扣
从C语言到C++_39(C++笔试面试题)next_permutation刷力扣
59 5
|
6月前
|
存储 编译器 C语言
从C语言到C++_22(继承)多继承与菱形继承+笔试选择题(下)
从C语言到C++_22(继承)多继承与菱形继承+笔试选择题
45 0
|
6月前
|
Java 编译器 定位技术
从C语言到C++_22(继承)多继承与菱形继承+笔试选择题(中)
从C语言到C++_22(继承)多继承与菱形继承+笔试选择题
45 0
|
6月前
|
安全 程序员 C语言
从C语言到C++_22(继承)多继承与菱形继承+笔试选择题(上)
从C语言到C++_22(继承)多继承与菱形继承+笔试选择题
48 0
|
6月前
|
C语言 C++
从C语言到C++⑧(第二章_类和对象_下篇_续)笔试选择题和OJ题
从C语言到C++⑧(第二章_类和对象_下篇_续)笔试选择题和OJ题
37 0
|
23天前
|
存储 编译器 对象存储
【C++打怪之路Lv5】-- 类和对象(下)
【C++打怪之路Lv5】-- 类和对象(下)
21 4
|
23天前
|
编译器 C语言 C++
【C++打怪之路Lv4】-- 类和对象(中)
【C++打怪之路Lv4】-- 类和对象(中)
20 4
|
23天前
|
存储 安全 C++
【C++打怪之路Lv8】-- string类
【C++打怪之路Lv8】-- string类
17 1
|
1月前
|
存储 编译器 C++
【C++类和对象(下)】——我与C++的不解之缘(五)
【C++类和对象(下)】——我与C++的不解之缘(五)
|
1月前
|
编译器 C++
【C++类和对象(中)】—— 我与C++的不解之缘(四)
【C++类和对象(中)】—— 我与C++的不解之缘(四)