1,Q:MFC消息映射机制是怎样?
A: 在按下鼠标左键等操作时,将产生一个WM_LBUTTONDWON消息,然后被系统放入该应用程序的消息循环中(每个应用程序独有)。然后系统在该应用程序的每个能接收和处理消息的类中,定义维护了一个消息和消息函数静态对照表,即:消息映射表。当有消息需要处理时,程序只要搜索该消息静态表,查看表中是否含有该消息,就可知道该类能否处理此消息。如果能处理该消息,就可以找到并调用对应的消息处理函数。应用程序通过一个消息循环不断的获取消息并分发给消息处理函数处理消息。while((bret=GetMessage(&msg,NULL,0,0))!=0){
if(bret==-1)
return;
TranslateMessage(&Msg);
DispatchMessage(&msg);
}
2,Q:MFC的窗口创建过程?
A:一:设计一个窗口类;二:注册窗口类,ATOM RegisterClass(CONST WNDCLASS * lpWndClass);三:创建窗口CreatWindow();四:显示及更新窗口ShowWindow()UpdateWindow();五:编写消息循环;六:编写窗口过程LRESULT CALLBACK windowProc();
3,Q:MFC不得不掌握的基础绘画知识点?
A:设备描述表(DC):在不能响应WM_PAINT时调用,hdc = GetDC(hwnd);ReleaseDC(hwnd,hdc);在响应WM_PAINT下用BeginPaint(hwd,&ps);EndPaint();CDC类:设备描述表DC的封装类,CDC * pDC = GetDC();pDC->MoveTo();pDC->LineTo();ReleseDC(pDC);
CClientDC类:派生于CDC,CClientDC dc(this);dc.MoveTo();dc.LineTo();
CWindowDC类:类似于CClientDC类,可以访问整个窗口区域,搭配GetDesktopWindow()可以在桌面画线
CPaintDC类:封装了beginpaint()和endpaint();
绘制彩色线条:CPen pen(PS_SOLID,1,RGB(255,0,0));CClientDC dc(this); CPen*pOldPen = dc.SelectObject(&pen);dc.MoveTo(m_ptOrigin);dc.LineTo(point);dc.SelectObject(pOldPen);
填充矩形画刷:CBrush brush(RGB(25,0,0));CClientDC dc(this);dc.FillRect(CRect (m_ptOrigin,point),&brush);
4,Q:STL不得不掌握的基础知识点?
A:STL主要包含容器、算法、迭代器三大核心部分;容器:可容纳各种数据类型的多元素数据结构;包含了绝大多数数据结构如数组、链表、字符串、队列、堆栈、树等;
迭代器:可依次存取容器中元素的东西;
算法:用来操作容器中的元素的函数模板。包含了诸如增、删、改、查、排序等系统(全局)函数模板。例如,STL用sort()来对一个vector中的数据进行排序,用find()来搜索一个list中的对象。函数本身与他们操作的数据的结构和类型无关,因此他们可以在简单数组及高度复杂容器的任何数据结构上使用。
STL提供了七种基本容器,它们被划分为两大类,即序列式容器和关联式容器。除了基本容器外,STL还提供了一些其它类型的容器,如容器适配器(容器适配器可以看作是由其它容器实现的容器)。
序列式容器中的元素顺序与元素值无关,只与元素插入的次序和存放位置有关。STL预先定义了三种序列式容器,即Vectors(向量)、Deque(双向队列)和List(双向链表)。
关联式容器中的元素位置是按元素值的大小自动排序的,缺省情况下为升序排列。其元素顺序与元素值有关,与元素插入的先后次序无关。关联式容器的底层实现是二叉搜索树的形式。STL中预先定义的关联式容器有Sets与Multisets(集合与多重集合)以及Map与Multimap(映射与多重映射) 。
算法:STL提供了大约70多个已经实现了的算法的函数模板,#include<algorithm >,<numeric>和<functional>;是全局函数;
迭代器:可以把迭代器看作一个类似于指向容器中元素的被泛化了的普通指针,尽管迭代器类似于指针,但迭代器决不是普通的指针。它们的区别是:指针是指向它所要访问的数据元素的地址,而迭代器是指向它所要访问的数据元素的位置(即容器的某个位置的下标)。但它们也有相同之处,即要访问它们所指的数据元素时,都是在其前面缀“*”运算符。
s.begin()——指向向量容器s的第一个元素位置;
s.end()——指向向量容器s的末尾位置(即最后一个元素所在位置的下一个位置);
ostream_iterator<int>(cout, ", ")——是一个输出流迭代器(实例),其中的ostream_iterator是一个输出迭代器的类模板。
假设vecList是一个向量类型容器对象,这些操作都是vector类的公有成员函数;
在向量容器中声明迭代器
声明向量容器的迭代器
vector类内嵌了一个iterator类,它是vector类的一个public成员。通过iterator类可以声明向量容器的一个或多个迭代器,例如语句:
vector<int>::iterator intVeciter;
将intVecIter声明为int类型的向量容器迭代器。
2、向量容器迭代器的运算表达式
++intVecIter 将迭代器intVecIter前移一个位置,使其指向容器中的下一个元素;
--intVecIter 将迭代器intVecIter后移一个位置,使其指向容器中的前一个元素;
*intVecIter 返回当前迭代器位置上的元素值。
3、容器的成员函数begin()和end()
不仅仅向量容器,所有容器都包含成员函数begin()和end()。函数begin()返回容器中第一个元素的位置;函数end()返回容器中最后一个元素的下一个位置。这两个函数都没有参数。
5,Q:函数指针及指针函数?
函数指针:指向函数代码首地址的指针变量。int (*f)(int x);int func(int x);
int (*f) (int x);
f=func;
指针函数:返回指针的函数
6,Q:this指针?
this指针只能在一个类的成员函数中调用,它表示当前对象的地址。this在成员函数的开始前构造的,在成员的结束后清除。this是通过函数参数的首参数来传递的。this指针是在调用之前生成的。当对一个对象调用成员函数时,编译程序先将对象的地址赋给this指针,然后调用成员函数,每次成员函数存取数据成员时,也隐含使用this指针。
7,Q:const,static,extern?
一般程序的由new产生的动态数据存放在堆区,函数内部的自动变量存放在栈区,全局变量和static变量放在全局数据区。extern可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中。使用extern“C”主要是因为C++语言在编译的时候为了实现多态,会将函数名和函数结合起来形成另外一种函数名。当你要在C++中调用C函数时,由于名字的不同,所以它会找不到所调用的这个函数的定义,因而会出错。8,Q:基类指针 派生类指针?
1,用基类指针引用一个派生类对象,由于派生类对象也是基类的对象,所以这种引用是安全的,但是只能引用基类成员。若试图通过基类指针引用那些只在派生类中才有的成员,编译器会报告语法错误。(解决该问题的答案是虚函数和多态性)。2,用派生类指针引用基类的对象。这种引用方式会导致语法错误。派生类指针必须先强制转换为基类指针,这种方法是安全的。
3,如果基类和派生类都定义了“相同名称之函数”,那么通过对象指针调用成员函数时,到底调用了那个函数,必须视该指针的原始类型而定,而不是视指针实际所指的对象的类型而定,这与第1点其实意义相通
我们常常将一个基类指针指向子类对象,以此来实现多态。但是,当调用delete析构这个基类指针的话,就有一个潜藏的危机:当子类对象经由一个基类指针被删除,而该基类带着一个非virtual析构函数,其结果是不能预料的——实际执行时通常发生的是对象的子类成分没有被销毁!
消除这个问题的做法很简单:给基类一个virtual析构函数。只有当类中含有virtual函数时,我们才为它声明virtual析构函数。2 不带virtua;析构函数的指针的类最好别做基类。3 不要试图继承一个标准容器或任何其他带有非virtual析构函数的类。
当你想拥有一个抽象类,但是没有纯虚函数时,怎么办?
答案是为这个类声明一个纯虚的析构函数,然后再为这个析构函数提供一份定义(因为析构子类时必须要调用它)。这个规则只是针对于那些设计目的为了多态的类。
带有多态性质的基类应该声明一个virtual析构函数,如果一个类有任何的virtual函数,它就应该拥有一个virtual析构函数。如果类的设计目的不是为了作为基类使用,或者不是为了具备多态性,就不应该声明virtual析构函数。在构造和析构期间不要调用virtual函数,因为这类调用从不下降到子类中。
9,Q:重载(overload)、覆盖(override)、隐藏(hide)的区别?
成员函数被重载的特征(1)相同的范围(在同一个类中);
(2)函数名字相同;
(3)参数不同;
(4)virtual 关键字可有可无。
覆盖(重写)是指派生类函数覆盖基类函数,特征是
(1)不同的范围(分别位于派生类与基类);
(2)函数名字相同;
(3)参数相同;
(4)基类函数必须有virtual 关键字。
“隐藏”是指派生类的函数屏蔽了与其同名的基类函数,规则如下
(1)如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual关键字,基类的函数将被隐藏(注意别与重载混淆)。
(2)如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual 关键字。此时,基类的函数被隐藏(注意别与覆盖混淆)
3种情况怎么执行:
1。重载:看参数
2。隐藏:用什么就调用什么
3。覆盖:调用派生类
10,Q:进程和线程的区别?
进程间是独立的,这表现在内存空间,上下文环境;线程运行在进程空间内。同一进程所产生的线程共享同一内存空间。
(1)地址空间:线程是进程内的一个执行单元;进程至少有一个线程;它们共享进程的地址空间;而进程有自己独立的地址空间;
(2)进程是资源分配和拥有的单位,同一个进程内的线程共享进程的资源
(3)线程是处理器调度的基本单位,但进程不是.
(4)二者均可并发执行.