C++/MFC 试题

匿名网友 匿名网友 发布于: 2015-08-30 00:00:00
阅读 142 收藏 0 点赞 0 评论 0

一.填空题 (26 分 )
1 . WIN32 平台下, sizeof(short) = __2__ , sizeof(int) = __4__ , sizeof(long) = __4__ 。 (3 分 ) /// sizeof(char) = 1;sizeof(double) = 8;sizeof(float) = 4;
2 .请给出如下程序的结果 (2 分 )
int a = 3;
int b = a << 3; /// 00000011左移三位为00011000,即24 a = __3__ , b = __24__ 。 3 .请 给出如下程序的结果 (2 分 ) int aaa = 0x01; htonl(aaa) = _16^6___ 。/// 0x01000000 十六进制数,转换为十进制为16的6次方,即16777216 4 .请给出如下程序的结果 (2 分) #define MAX_NUM 100+200 int nTemp = MAX_NUM*10; ///宏的功能只是简单的字符替换,MAX_NUM*10表示100+200*10,所以用宏要小心 则 Temp = __2100__ 。 5 .请给出如下程序的结果 (3 分 ) char szTemp[1000] = ""; int nLen1 = sizeof(szTemp); int nLen2 = strlen(szTemp);/// strlen的计算结果不包含结束符'' strcpy(szTemp, "abc"); int nLen3 = sizeof(szTemp); int nLen4 = strlen(szTemp); int nTemp[100]; int *pTemp = nTemp; int nLen5 = sizeof(pTemp);/// 在32位系统中,指针只占4位字节,不管它指向地址的内容有多大! char szResult[200] = ""; sprintf(szResult, "%d,%d,%d,%d,%02d.", nLen1, nLen2, nLen3, nLen4, nLen5); 则 szResult = _1000,0,1000,3,04___ 。 6 . MFC 中,大部分类是从哪个类继承而来( CCmdTarget 、 CObject 、 CWinApp 、 CWnd )? (2 分 )__CObject __ 7 .内存是进程范围 or 线程范围; __进程__ /// 进程有独立的内存,是线程的管理者,线程是进程的执行者 CPU 调度时,针对进程 or 线程; __线程__ /// 线程才是执行者 函数调用堆栈,针对进程 or 线程。 _进程___(3 分 ) /// 进程才有独立内存,堆栈属于内存的一部分 8 .调用函数 bbb 后,输出是什么 (4 分 ) void ccc(int x) /// 参数为数值传递,不是引用传递 { char szTemp[10] = ""; x = 2; sprintf(szTemp, "%d,", x); afxDump << szTemp; /// afxDump表示输出信息到MFC调试(Debug)窗口 if(x = 3) ///注意这里不是"=="而是"=",所以if条件是成立的 { int x = 4; sprintf(szTemp, "%d,", x); afxDump << szTemp; } sprintf(szTemp, "%d,", x); afxDump << szTemp; } void bbb() { char szTemp[10] = ""; int x = 7; ccc(x); sprintf(szTemp, "%d,", x); afxDump << szTemp; } 二.改错题 ( 总共 15 分 , 每题 5 分 ) 。 1 .下面代码有何错误 void func1() { int *pa = NULL; func2(pa); /// 函数返回后pa仍然是空指针 delete pa; /// pa仍然是空指针,pb申请的空间并没有被delete掉 } void func2(int *pb) { pb = new int(5); /// pb重新申请了堆空间 } 2 .下面代码有何错误 void func2(int *value) { *value = 2; /// value为空指针,不能被取值,所以*value是错误的 } void func1() { int *p = 0; func2(p); } 3 . int func1(int& b) /// 参数b的类型的整型 { return 0; } void func2() { int bbb = 3; func1(&bbb); /// 函数参数的引用调用不需要用符号"&" func1(bbb); } func2 中有何错误, func1 的参数 b 的类型是什么。 三.简答题 (64 分 ) PS:以下答案是随笔所写,请读者做进一步的深入了解。 1. 请简述 C 、 C++ 、 VC 、 MFC 在概念上的区别 (4 分 ) 答:C是面向过程编程的语言; C++是面向对象编程的语言; VC是微软提供的方便于开发C++程序的一套开发工具。 MFC(Microsoft Function Class),是微软提供的一套函数类库,里面封装了许多Windows API函数,方便开发者调用。 2 .请写一个函数重载的简单例子 (4 分 ) 答: int add(int a,int b) { return (a + b); } 函数重载:/// 函数重载是指函数名相同,但参数类型或返回值可能不同的函数。 float add(float a,float b) { return (a + b); } 3. 用什么函数开启新进程、线程。 (4 分 ) 答:CreateProccess()创建进程; CreateThread()创建线程 MFC中还提供了_beginthread()与_beginthreadex()函数创建线程 4.SendMessage 和 PostMessage 有什么区别 (4 分 ) 答:SendMessage:发送消息后,等待消息处理完毕后才继续执行自身的程序。 PostMessage:发送消息后不等待消息处理即继续执行自身的程序。 5.WaitForSingleObject 有何作用; m_pThrd 的类型是 CWinThread* 时, WaitForSingleObject(m_pThrd->m_hThread, INFINITE); 有何作用。 (4 分 )
答:WaitForSingleObject是表示等待线程的一个函数。
参数为INFINITE表示一直等待线程CWinThread执行结束后,再继续处理自身程序。

6. __stdcall 、 __cdecl 、 __pascal 在什么方面有所不同。 (4 分 )
答:这些都是一些函数参数的调用约定,告诉编译器函数参数压栈的顺序,以及压入堆栈的内容由谁来清除,是调用者还是函数本身清除堆栈的内容。简单列表如下:
Directive Parameter order Clean-up Passes parameters in registers?
pascal Left-to-right Routine No
cdecl Right-to-left Caller No
stdcall Right-to-left Routine No

7 .请把下述代码加上异常处理。 (6 分 )
int MyWriteFile(CString strFileName, CString strText)
{
int nRet = 0;

CFile myFile;
myFile.Open(strFileName, CFile::modeWrite|CFile::shareExclusive|CFile::modeCreate, NULL);

int nLen = strText.GetLength();
myFile.Write((char*)(LPCSTR)strText, nLen);

myFile.Close();

return nRet;
}
答:
int MyWriteFile(CString strFileName, CString strText)
{
int nRet = 0;

CFile myFile;
__try
{
nRet = myFile.Open(strFileName,
CFile::modeWrite|CFile::shareExclusive|CFile::modeCreate, NULL);
if(!nRet)
{
/// 输出异常信息
__leave;/// 结束try块,跳到__finaly代码块
}
int nLen = strText.GetLength();
nRet = myFile.Write((char*)(LPCSTR)strText, nLen);
if(!nRet)
{
/// 输出异常信息
__leave;/// 结束try块,跳到__finaly代码块
}
}
__finaly
{
myFile.Close();
}
return nRet;
}
8 .请解释“ func ”为何种类型,这种类型的作用什么,变量 ttt 的值是多少? (6 分 )
typedef int (*func)(int, int*);
int xxx(int a, int *p)
{
return a + *p;
}
int dowork(func aaa, int bbb, int *ccc)
{
return aaa(bbb, ccc);
}
int sss = 4;
int ttt = dowork(&xxx, 3, &sss);
答:func表示一个函数指针,它指向参数为int,int*,返回值为int的函数。ttt的值为7
9 .请问下述代码中 : int operator+(… )起什么作用? this 是什么? ccc 的值最终为多少? (6 分 )
class Fruit
{
public:
Fruit()
{
weight = 2;
}
Fruit(int w)
{
weight = w;
}
int operator+(Fruit f)
{
return this->weight * f.weight;
}
private:
int weight;
};
Fruit aaa;
Fruit bbb(4);
int ccc = aaa + bbb;
答:int operator+(… )表示重载类的“+”号运算符,this表示对象本身的指针,本例中它指向类的对象aaa;ccc最终的结果为8(8 = 2 * 4)。

10. 请解释下面代码采用了何种 C++ 特性( C 语言不具备),作用是什么? (6 分 )
template
T sum(T a, T b)
{
return (a + b);
}
答:表示函数模板,用于将一类功能相同,参数类型和返回值不同的函数抽象为一个模板,方便模板函数调用。

11 .请解释 aaa.h 中下面代码的功能 (5 分 )
#if !defined(AFX_MYSUDU_H__9B952BEA_A051_4026_B4E5_0598A39D2DA4__INCLUDED_)
#define AFX_MYSUDU_H__9B952BEA_A051_4026_B4E5_0598A39D2DA4__INCLUDED_
… …
#endif
答:这是预处理命令,可以保证多次包含此头文件时,只编译一次代码。

12 . CMemoryState 主要功能是什么 (5 分 )
答:用于检测内存泄露。

13 .请阅读下述代码,写出程序执行的结果( 6 分)
#include
using namespace std;

class CBase
{
public:
virtual void print()
{
cout<< "base" << endl; } void DoPrint() { print(); } }; class CChild1: public CBase { public: virtual void print() { cout<< "child1" << endl; } }; class CChild2: public CBase { public: virtual void print() { cout<< "child2" << endl; } }; void DoPrint(CBase *base) { base->DoPrint();
}

void main()
{
CBase* base = new CBase();
CChild1* child1 = new CChild1();
CChild2* child2 = new CChild2();
DoPrint(child1);
DoPrint(child2);
DoPrint(base);

delete base;
base = child1;
base->print();
delete child1;
delete child2;
}
答:
child1
child2
base
child1
这是C++中类的虚函数实现多态的一个实例。

1.虚函数和纯虚函数可以定义在同一个类(class)中,含有纯虚函数的类被称为抽象类(abstract class),而只含有虚函数的类(class)不能被称为抽象类(abstract class)。
2. 虚函数可以被直接使用,也可以被子类(sub class)重载以后以多态的形式调用,而纯虚函数必须在子类(sub class)中实现该函数才可以使用,因为纯虚函数在基类(base class)
只有声明而没有定义。
3. 虚函数和纯虚函数都可以在子类(sub class)中被重载,以多态的形式被调用。
4.虚函数和纯虚函数通常存在于抽象基类(abstract base class -ABC)之中,被继承的子类重载,目的是提供一个统一的接口。
5.虚函数的定义形式:virtual void funtion1(int param1,int param2,…);
纯虚函数的定义形式:virtual void funtion1(int param1,int param2,…) = 0;
在虚函数和纯虚函数的定义中不能有static标识符,原因很简单,被static修饰的函数在编译时候要求前期bind,然而虚函数却是动态绑定(run-time bind),而且被两者修饰的函数生命周期(life recycle)也不一样。
6. 如果一个类中含有纯虚函数,那么任何试图对该类进行实例化的语句都将导致错误的产生,因为抽象基类是不能被直接调用的。必须被子类继承重载以后,根据要求调用其子类的方法。
基类:
class A
{
public:
A();
void f1();
virtual void f2();
virtual void f3()=0;
virtual ~A();
};
子类:
class B : public A
{
public:
B();
void f1();
void f2();
void f3();
virtual ~B();
};
主函数:
int main(int argc, char* argv[])
{
A *m_j=new B();
m_j->f1();
m_j->f2();
m_j->f3();
delete m_j;
return 0;
}
f1()是一个普通的重载.
调用m_j->f1();会去调用A类中的f1(),它是在我们写好代码的时候就会定好的.
也就是根据它是由A类定义的,这样就调用这个类的函数.
f2()是虚函数.
调用m_j->f2();会去调用B类中的f2(),而不是A类的f2(),这是由于new了B类的
对象.
f3()与f2()一样,只是在基类中不需要写函数实现.

评论列表
文章目录