《孙鑫c++教程(全20讲)讲义》由会员分享,可在线阅读,更多相关《孙鑫c++教程(全20讲)讲义(134页珍藏版)》请在金锄头文库上搜索。
1、1.Windows程序内部运行原理,主讲人:孙鑫,http:/www.sunxin.org,Windows应用程序,操作系统,计算机硬件之间的相互关系,http:/www.sunxin.org,关于API,向下的箭头表示应用程序可以通知操作系统执行某个具体的动作,如操作系统能够控制声卡发出声音,但它并不知道应该何时发出何种声音,需要应用程序告诉操作系统该发出什么样的声音。这个关系好比有个机器人能够完成行走的功能,但是,如果人们不告诉它往哪个方向上走,机器人是不会主动行走的。这里的机器人就是操作系统,人们就是应用程序。,http:/www.sunxin.org,关于API,那么,应用程序是如何通
2、知操作系统执行某个功能的呢?有过编程经验的读者都应该知道,在应用程序中要完成某个功能,都是以函数调用的形式实现的,同样,应用程序也是以函数调用的方式来通知操作系统执行相应的功能的。操作系统所能够完成的每一个特殊功能通常都有一个函数与其对应,也就是说,操作系统把它所能够完成的功能以函数的形式提供给应用程序使用,应用程序对这些函数的调用就叫做系统调用,这些函数的集合就是Windows操作系统提供给应用程序编程的接口(Application Programming Interface),简称Windows API。如CreateWindow就是一个API函数,应用程序中调用这个函数,操作系统就会按照
3、该函数提供的参数信息产生一个相应的窗口。,http:/www.sunxin.org,关于消息及消息队列,向上的箭头表示操作系统能够将输入设备的变化上传给应用程序。如用户在某个程序活动时按了一下键盘,操作系统马上能够感知到这一事件,并且能够知道用户按下的是哪一个键,操作系统并不决定对这一事件如何作出反应,而是将这一事件转交给应用程序,由应用程序决定如何对这一事件作出反应。好比有个蚊子叮了我们一口,我们的神经末梢(相当于操作系统)马上感知到这一事件,并传递给了我们的大脑(相当于应用程序),我们的大脑最终决定如何对这一事件作出反应,如将蚊子赶走,或是将蚊子拍死。对事件作出反应的过程就是消息响应。,h
4、ttp:/www.sunxin.org,关于消息及消息队列,操作系统是怎样将感知到的事件传递给应用程序的呢?这是通过消息机制(Message)来实现的。操作系统将每个事件都包装成一个称为消息的结构体MSG来传递给应用程序,参看MSDN。 MSG结构定义如下: typedef struct tagMSG HWND hwnd; UINT message; WPARAM wParam; LPARAM lParam; DWORD time; POINT pt; MSG;,http:/www.sunxin.org,关于句柄,句柄(HANDLE),资源的标识。 操作系统要管理和操作这些资源,都是通过句柄来
5、找到对应的资源。按资源的类型,又可将句柄细分成图标句柄(HICON),光标句柄(HCURSOR),窗口句柄(HWND),应用程序实例句柄(HINSTANCE)等等各种类型的句柄。操作系统给每一个窗口指定的一个唯一的标识号即窗口句柄。,http:/www.sunxin.org,从变量的类型区分变量的用途,int x,y; x=30; y=30; /x和y既可以用来表示坐标点,也可以用来表示宽度和高度,还可以用来表示身高和体重。 typedef int WIDTH typedef int HEIGHT WIDTH x; HEIGHT y; /好处:我们从变量的类型上就可以知道x和y是用来表示宽度和
6、高度。,http:/www.sunxin.org,WinMain函数,Windows程序的入口函数 int WINAPI WinMain( HINSTANCE hInstance, / handle to current instance HINSTANCE hPrevInstance, / handle to previous instance LPSTR lpCmdLine, / command line int nCmdShow / show state );,http:/www.sunxin.org,窗口的创建,创建一个完整的窗口需要经过下面四个操作步骤: 设计一个窗口类; 注册窗口类
7、; 创建窗口; 显示及更新窗口。,http:/www.sunxin.org,设计窗口类,typedef struct _WNDCLASS UINT style; WNDPROC lpfnWndProc; int cbClsExtra; int cbWndExtra; HANDLE hInstance; HICON hIcon; HCURSOR hCursor; HBRUSH hbrBackground; LPCTSTR lpszMenuName; LPCTSTR lpszClassName; WNDCLASS;,http:/www.sunxin.org,窗口类的类型,在我们的程序中经常要用到一
8、类变量,这个变量里的每一位(bit)都对应某一种特性。当该变量的某位为1时,表示有该位对应的那种特性,当该位为0时,即没有该位所对应的特性。当变量中的某几位同时为1时,就表示同时具有几种特性的组合。一个变量中的哪一位代表哪种意义,不容易记忆,所以我们经常根据特征的英文拼写的大写去定义一些宏,该宏所对应的数值中仅有与该特征相对应的那一位(bit)为1,其余的bit都为0。我们使用goto definition就能发现CS_VREDRAW=0x0001,CS_HREDRAW=0x0002,CS_DBLCLKS =0x0008,CS_NOCLOSE=0x0200。他们的共同点就是只有一位为1,其余位
9、都为0。如果我们希望某一变量的数值既有CS_VREDRAW特性,又有CS_HREDRAW特性,我们只需使用二进制OR(|)操作符将他们进行或运算相组合,如style=CS_VREDRAW | CS_HREDRAW | CS_NOCLOSE。如果我们希望在某一变量原有的几个特征上去掉其中一个特征,用取反()之后再进行与(&)运算,就能够实现,如在刚才的style的基础上去掉CS_NOCLOSE特征,可以用style & CS_NOCLOSE实现。,http:/www.sunxin.org,窗口过程函数,第二个成员变量lpfnWndProc指定了这一类型窗口的过程函数,也称回调函数。回调函数的原理
10、是这样的,当应用程序收到给某一窗口的消息时(还记得前面讲过的消息通常与窗口相关的吗?),就应该调用某一函数来处理这条消息。这一调用过程不用应用程序自己来实施,而由操作系统来完成,但是,回调函数本身的代码必须由应用程序自己完成。对于一条消息,操作系统到底调用应用程序中的哪个函数(回调函数)来处理呢?操作系统调用的就是接受消息的窗口所属的类型中的lpfnWndProc成员指定的函数。每一种不同类型的窗口都有自己专用的回调函数,该函数就是通过lpfnWndProc成员指定的。,http:/www.sunxin.org,窗口过程函数,举例:汽车厂家生产汽车好比应用程序创建窗口,用户使用汽车好比操作系统
11、管理窗口,某种汽车在销售前就指定好了修理站(类似回调函数),当用户的汽车出现故障后(类似窗口收到消息),汽车用户(类似操作系统)自己直接找到修理站去修理,不用厂家(类似应用程序)亲自将车送到修理站去修理,但修理站还得由厂家事先建造好。,http:/www.sunxin.org,2.掌握C+,主讲人:孙鑫,http:/www.sunxin.org,C+的标准输入输出流,C+中提供了一套输入输出流类的对象,它们是cin 、cout和cerr,对应c语言中的三个文件指针stdin、stdout、stderr,分别指向终端输入、终端输出和标准出错输出(也从终端输出)。cin与一起完成输入操作,cout
12、、cerr与i; 注意箭头的方向。在输出中我们还使用endl(end of line),表示换行,注意最后一个是字符l,而不是数字1,endl相当于C语言的n,表示输出一个换行。,http:/www.sunxin.org,C+的特性,构造函数 1、构造函数最重要的作用是创建对象本身 。 2、C+规定,每个类必须有一个构造函数,没有构造函数,就不能创建任何对象。,http:/www.sunxin.org,C+的特性,构造函数 3、C+又规定,如果一个类没有提供任何的构造函数,则C+提供一个默认的构造函数(由C+编译器提供),这个默认的构造函数是一个不带参数的构造函数,它只负责创建对象,而不做任何
13、的初始化工作。 4、只要一个类定义了一个构造函数,不管这个构造函数是否是带参数的构造函数,C+就不再提供默认的构造函数。也就是说,如果为一个类定义了一个带参数的构造函数,还想要无参数的构造函数,则必须自己定义。,http:/www.sunxin.org,C+的特性,析构函数 1、当一个对象生命周期结束时,其所占有的内存空间就要被回收,这个工作就由析构函数来完成。 2、析构函数是“反向”的构造函数,析构函数不允许有返回值,更重要的是析构函数不允许带参数,并且一个类中只能有一个析构函数。,http:/www.sunxin.org,C+的特性,析构函数 3、析构函数的作用正好与构造函数相反,对象超出
14、其作用范围,对应的内存空间被系统收回或被程序用delete删除时,析构函数被调用。 4、根据析构函数的这种特点,我们可以在构造函数中初始化对象的某些成员变量,给其分配内存空间(堆内存),在析构函数中释放对象运行期间所申请的资源。,http:/www.sunxin.org,C+的特性,函数的重载 重载构成的条件:函数的参数类型、参数个数不同,才能构成函数的重载。,http:/www.sunxin.org,C+的特性,函数的重载 分析以下两种情况,是否构成函数的重载。 第一种情况:(1)void output(); (2)int output(); 第二种情况:(1)void output(int
15、 a,int b=5); (2)void output(int a);,http:/www.sunxin.org,C+的特性,this指针 1、this指针是一个隐含的指针,它是指向对象本身,代表了对象的地址 2、一个类所有的对象调用的成员函数都是同一代码段。那么成员函数又是怎么识别属于同一对象的数据成员呢?原来,在对象调用pt.output(10,10)时,成员函数除了接受2个实参外,还接受到了一个对象s的地址。这个地址被一个隐含的形参this指针所获取,它等同于执行this= 等价于 this-x=0。,http:/www.sunxin.org,小技巧:在以后的MFC编程中,如果在成员函数
16、中想调用同类中的某个成员,可以使用VC+提供的自动列出成员函数功能,使用this-,VC+将列出该类中的所有成员,我们可以从列表中选择我们想调用的成员。 自动列出成员函数功能,可以提高编写速度,减少拼写错误。我们经常不能完全记住某个函数的完整拼写,但却能够从列表中辨别出该函数,自动列出成员函数的功能在这时就显得更加有用了。事实上,在各种IDE编程环境中,我们通常都不可能记住也没有必要记住所有的函数,只要将常用的函数记住,其他不常用的函数只要记住其大概的写法和功能,在调用该函数时可以从自动列出成员函数中选取,这样可以大大节省我们的学习时间。我们不用花费大量的时间去死记硬背许多函数,利用自动列出成员函数功能和帮助系统,就能够在编程时顺利地使用这些函数,等用的次数多了,也就在不知不觉中完全掌握了这些函数。,http:/www.sunxin.org,C+的特性,类的继承 在C+中,给我们提供了一种重要