代码学习记录

1. STDMETHOD

STDMETHOD,定义了一个返回HRESULT类型的虚方法
举例说明:
一个如下的函数

STDMETHOD(fun)(int i)

其展开以后变成:

virtual HRESULT __stdcall fun(int i); 

这样就定义了一个函数fun。
当然,这个虚函数只能放在接口定义中,所以STDMETHOD宏是用于定义接口用,放在头文件中用。

2. volatile关键字

特性:
易变性
编译器对volatile修饰的变量,当要读取这个变量时,任何情况下都会从内存中读取,而不会从寄存器缓存中读取(因为每次都从内存中读取体现出变量的“易变”),防止不同线程寄存器和内存读到不同的值
不可优化性
编译器不会对volatile修饰的变量进行任何优化
顺序性
程序的乱序优化:保证一段代码输出结果的前提下,将各条代码的实际执行顺序进行优化调整
volatile变量与volatile变量间代码的顺序,编译器不会进行乱序优化,但是volatile变量与非volatile变量代码的顺序,编译器不保证顺序,可能会进行乱序优化
参考:https://www.cnblogs.com/Joezzz/p/10271920.html

总结:
多线程编程,并发访问/修改全局变量,通常都会建议加上Volatile关键词修饰,来防止C/C++编译器进行不必要的优化。

3. ATL_NO_VTABLE

在用ATL编写COM组件时,在类前面都有一个宏ATL_NO_VTABLE,这个宏的定义如下: #define __declspec(novtable) ATL_NO_VTABLE;

因为ATL是通过多重继承来实现COM组件的;

继承层次中的每个类都有自己的虚函数表,所以在继承层次很深的情况下,虚函数表会变 得非常宏大,如果用ATL_NO_VTABLE宏来阻止生成函数表,就会有限的减少组件的长度。
事实上ATL中预先实现的接口类基本上都使用了这个宏。只要有继承树结构的最下层的几个类 CComObject、CComAggObject、CCompolyObject、CComContainedobject能够正确生成 VTABLE就可以了。也正因为这个原因,这几个类都没有使用ATL_NO_VTABLE.

4. L"字符串"

VC支持ascii和unicode两种字符类型,用_T可以保证从ascii编码类型转换到unicode编码类型的时候,程序不需要修改
字符串前面加L表示该字符串是Unicode字符串;
L"我的字符串" 表示将ANSI字符串转换成unicode的字符串,就是每个字符占用两个字节。

strlen("asd") = 3; 
strlen(L"asd") = 6; 

5. _T(“字符串”)

_T宏可以把一个引号引起来的字符串,根据你的环境设置,使得编译器会根据编译目标环境选择合适的(Unicode还是ANSI)字符处理方式

如果你定义了UNICODE,那么_T宏会把字符串前面加一个L。这时 _T(“ABCD”) 相当于 L"ABCD" ,这是宽字符串。

如果没有定义,那么_T宏不会在字符串前面加那个L,_T(“ABCD”) 就等价于 “ABCD”

6. GetmodulefileNameX

GetmodulefileName() 函数返回当前进程已加载可执行或DLL文件的完整路径名(以’\0’终止),该模块必须由当前进程地址空间加载。如果想要获取一个已加载模块的文件路径,可以使用GetmodulefileNameEx()函数

DWORD WINAPI GetmodulefileName(
  _In_opt_  HMODULE hModule,   //应用程序或DLL实例句柄,NULL则为获取当前程序可执行文件路径名
  _Out_     LPTSTR lpFilename, //接收路径的字符串缓冲区
  _In_      DWORD nSize        //接收路径的字符缓冲区的大小
);

确切的说,GetmodulefileName的定义是一个宏,在UNICODE版本下,GetmodulefileName等同于GetmodulefileNameW,在ANSI版本下等同于GetmodulefileNameA

GetmodulefileNameAGetmodulefileNameW的区别在于它们的字符串参数的“字符宽度”,这两个函数的原型如下:

DWORD WINAPI GetmodulefileNameA( 
	HMODULE hModule, 
	LPSTR lpFilename, 
	DWORD nSize );

ANSI版本,第二个参数是LPSTR,也就是char*。

DWORD WINAPI GetmodulefileNameW( 
	HMODULE hModule, 
	LPWSTR lpFilename, 
	DWORD nSize );

//UNICODE版本,第二个参数是LPWSTR,也就是wchar_t*。

7. ShellExecuteW

功能是运行一个外部程序(或者是打开一个注册文件、打开一个目录、打印一个文件等等);
它可以打开电脑内的任何文件,也可以打开URL

ShellExecute(
hWnd: HWND, //指定父窗口句柄
Operation: PChar,//指定动作, 如: open、runas、print、edit、explore、find[2]
FileName: PChar,//指定要打开的文件或程序
Parameters: PChar,//给要打开的程序指定参数
Directory: PChar,//缺省目录
ShowCmd: Integer//打开选项
):

hWnd:

用于指定父窗口的句柄。当函数调用过程中出现错误时,它将作为Windows消息窗口的父窗口。

lpOperation:

用于指定要进行的操作,当参数为NULL时,认操作"open"。

“open”,表示执行由lpFile参数指定的程序,或者打开由lpFile参数指定的文件文件夹。

"explort",表示打开由lpFile参数指定的文件夹。

"print",表示打印由lpFile参数指定的文件

lpParameters:

若lpFile参数是一个可执行文件,则此参数指定命令行参数,否则此参数应设为NULL。

lpDirectory:

用于指定认目录。

nShowCmd:

用于指定程序窗口初始显示方式。 有如下参数
#define SW_HIDE             0   /*隐藏窗体,并激活另一个窗体*/
#define SW_SHOWnorMAL       1   /*与SW_RESTORE相同*/
#define SW_SHOWMINIMIZED    2   /*激活并以最小化的形式显示窗体*/
#define SW_SHOWMAXIMIZED    3   /*激活并以最大化的形式显示窗体*/
#define SW_MAXIMIZE         3   /*最大化指定的窗体*/
#define SW_SHOWNOACTIVATE   4   /*以上次的状态显示指定的窗体,但不激活它*/
#define SW_SHOW             5   /*激活窗体,并将其显示在当前的大小和位置上*/
#define SW_MINIMIZE         6   /*最小化指定的窗体,并激活另一个窗体*/
#define SW_SHOWMINNOACTIVE  7   /*以最小化形式显示指定的窗体,但不激活它*/
#define SW_SHOWNA           8   /*以当前的状态显示指定的窗体,但不激活它*/
#define SW_RESTORE          9   /*以原本的大小和位置,激活并显示指定的窗体*/
#define SW_SHOWDEFAULT      10  /*设置显示的状态由STARTUPINFO结构体指定*/

8. GetBuffer()和releaseBuffer()

GetBuffer()主要作用是将字符串的缓冲区长度锁定;
releaseBuffer()则是解除锁定,使得CString对象在以后的代码中继续可以实现长度自适应增长的功能

9. STDAPI

在WINNT.h文件中STDAPI宏定义如下:

#define STDAPI EXTERN_C HRESULT STDAPICALLTYPE

其中,

#define STDAPICALLTYPE __stdcall

综合解释为:
STDAPI只是一个宏定义,而该宏定义由两个宏定义(EXTERN_C和STDAPICALLTYPE)和HRESULT组成。
经过预编译,有如下结果:extern "c" HRESULT __stdcall
extern “c” 会指示编译器这部分代码按C语言的进行编译
HRESULT 函数返回值类型,如果函数正常执行,则返回S_OK
__stdcall 是一种函数调用约定关键字

10. CreateEvent

HANDLECreateEvent(
LPSecurity_ATTRIBUTESlpEventAttributes,// 安全属性
BOOLbManualReset,// 复位方式
BOOLbInitialState,// 初始状态
LPCTSTRlpName // 对象名称
);

参数:
lpEventAttributes:一般为NULL
bManualReset:创建的Event是自动复位还是人工复位。如果true,人工复位,一旦该Event被设置为有信号,则它一直会等到ResetEvent()调用时才会恢复为无信号。如果false,自动复位,一旦该Event被设置为有信号,则当有一个wait到它的Thread时, 该Event就会自动复位,变成无信号
bInitialState:初始状态,true,有信号,false无信号
lpName:事件对象的名称。您在OpenEvent函数中可能使用
返回值:
函数创建一个Event同步对象,如果CreateEvent调用成功的话,会返回新生成的对象的句柄,否则返回NULL。

11. time()

//头文件 <time.h>
time_t time(time_t *t);

如果t是空指针,直接返回当前时间。如果t不是空指针,返回当前时间的同时,将返回值赋予t指向的内存空间。
返回自纪元 Epoch(1970-01-01 00:00:00 UTC)起经过的时间,以秒为单位

#include <stdio.h>
#include <time.h>

int main ()
{
  time_t seconds;

  seconds = time(NULL);
  printf("自 1970-01-01 起的小时数 = %ld\n", seconds/3600);
  
  return(0);
}

输出

在这里插入图片描述

12. FindFirstChangeNotificationA

创建一个文件通知对象。该对象用于监视文件系统发生的变化

HANDLE FindFirstChangeNotification(
LPCTSTR lpPathName, // 指定要监视的目录
BOOL bWatchSubtree, // 指定是否监视lpPathName 目录下的所有子目录
DWORD dwNotifyFilter // 指定过滤条件
);

在这里插入图片描述

13. 函数声明后面加throw()

问题描述:
C++里面为什么有时候在函数声明的时候在后面加throw()关键字?

解释:
C++函数后面加关键字throw(something)限制,是对这个函数的异常安全作出限制;这是一种异常规范,只会出现在声明函数时,表示这个函数可能抛出任何类型的异常。

void fun() throw();      //表示fun函数不允许抛出任何异常,即fun函数是异常安全的。

void fun() throw(...);    //表示fun函数可以抛出任何形式的异常。

void fun() throw(exceptionType);    // 表示fun函数只能抛出exceptionType类型的异常。

14. CALLBACK

CALLBACK,即回调函数,是一个通过函数指针调用函数
如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用为调用它所指向的函数时,我们就说这是回调函数
回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。

回调函数是由开发者按照一定的原形进行定义的函数(每个回调函数都必须遵循这个原则来设计)
注意
① 回调函数必须有关键词 CALLBACK;
② 回调函数本身必须是全局函数或者静态函数,不可定义为某个特定的类的成员函数

相关文章

显卡天梯图2024最新版,显卡是电脑进行图形处理的重要设备,...
初始化电脑时出现问题怎么办,可以使用win系统的安装介质,连...
todesk远程开机怎么设置,两台电脑要在同一局域网内,然后需...
油猴谷歌插件怎么安装,可以通过谷歌应用商店进行安装,需要...
虚拟内存这个名词想必很多人都听说过,我们在使用电脑的时候...