c语言MFC程序怎么杀死线程?

  • 应用程序的部署和重新发布

Visual C++ 引入了两种编写托管代码的方法。这两种方法都旨在简化 COM 编程,并且使程序能够访问由 .NET 公共语言运行库提供的服务,如垃圾回收和语言互操作性。

  • C++ 托管扩展   通过使用这些扩展,您可继续在现有程序中编写 C++ 代码。

属性旨在提供一种快捷有效的方法来简化使用 Visual C++ 进行的 COM 编程。属性与 C++ 关键字一样,都是在源文件中使用并由编译器进行解释。属性可以修改现有代码的行为,甚至可以插入附加框架代码来完成基本任务,例如实现 ActiveX 控件、创建类工厂或者设置数据库命令的格式。几乎可以将属性应用到任何 Visual C++ 对象(如类、数据成员以及成员函数)上,还可以将属性作为独立的语句插入到源代码中。

Visual C++ 帮助包括介绍属性化编程的各个方面的属性演练。

  • /clr 编译器选项。

  • /Gi 编译器选项已从该编译器移除;Visual C++ 编译器不再进行增量编译。/Gi 将被该编译器无提示忽略。

  • /GD 编译器选项已从编译器中移除。

  • 与 C++ 托管扩展关联的新关键字。

  • /RTC 编译器选项。

  • /w 编译器选项现允许指定特定警告的行为。

  • /Wall 编译器选项现在允许您启用所有警告,包括默认情况下禁用的警告。

  • 默认情况下关闭的一列警告。

  • CVPACK 实用工具已被移除。

  • /DEBUGTYPE 链接器选项已被移除。 COFF 格式中的符号支持已被移除;现在必须将符号放置在 .pdb 文件中。

  • /GPSIZE 链接器选项已被移除。链接器现根据是否存在与 GP 相关的到数据的重定位来确定公用变量(未初始化的全局数据项)的最佳位置。

    • 在依赖项检查时排除文件(新过程)。

    • “属性”窗口提供了一个可自定义的网格,用于查看和修改项目中对象的属性。

    • 项目属性页允许指定项目的生成设置。

    • 向导现在是用 HTML 和 JScript 设计的,它们具有支持文本文件,从而使自定义向导的灵活性和可扩展性更高。

    • 自定义生成过程是新的预生成事件。

    • 不再提供导出 NMAKE 生成文件的功能。使用 devenv 命令行开关从命令行生成 Visual C++ 项目。

    • 使用 /Gf 和导入到新版本的 Visual C++ 中,“图像编辑器”工具栏出现在工作区的顶部。“选项”选择器现在位于“图像编辑器”工具栏的最右侧,并显示为一个带有下拉箭头的按钮。“选项”选择器按钮上的图标随所选择的工具而变化。

      “图像编辑器”工具栏上的“文本工具”对话框

      “文本工具”对话框的行为已从 Visual C++ 。

      已将新行输入到文本中。

      退出文本工具并提交更改。

      已退出文本工具并提交了更改。

      退出文本工具并提交更改。

      已退出文本工具并提交了更改。

      退出文本工具并放弃更改。

      将新的一行输入到文本中。

      将新的一行输入到文本中。

      这些更改使文本工具的行为与标准对话框和其他图像编辑器工具的行为更为相似。

      Visual C++ .NET 中包含的下列库可能是新增的,也可能是经过更改的。

      • ATL 项目的默认设置已更改。

      • 更多关于 ATL 方法的参考主题包含代码示例。

      • 新类 CImage 提供增强的位图支持,包括以 JPEG、GIF、BMP 和可移植网络图形 (PNG) 格式加载和保存图像的能力。

      • 新的字符串转换宏和类。

      • 实用工具类:CAdapt

      • 若干个 ATL 方法已被替换。

      • CComModule 的功能已分散到若干个新类中。

      ATL Server 是一组本机 C++ 类,开发人员可用它来创建 Web 应用程序、XML Web services 以及其他服务器应用程序。许多类还可以用于客户端应用程序或组件。

      • 如果内存分配失败,new 运算符可能引发异常或返回零。

      • 允许使用超过 2038 年的日期的新函数:

      • 新增 __int64 版本的字符串函数:

      • 新增 Unicode 版本的控制台函数:

      • 计算打印格式化数据所需的字符数的新增字符串函数:

      • 由于受 C99 发布的时间所限,此 Visual C++ 版本不符合该标准。

      • 有关 MFC 的参考主题包含数百个新的代码示例。

      • 静态强制类型转换和 MFC 消息映射   从 Visual C++ .NET 开始,MFC 对消息处理函数的返回类型和参数类型进行更严格的类型检查。这些新增行为通过使用错误信息标记潜在不安全的消息处理函数,来通知开发人员可能会遇到的问题。MFC 现对

        例如,过去开发人员可以对 ON_MESSAGE 或 ON_REGISTERED_MESSAGE 使用返回 void 而非 LRESULT 的成员函数,并且编译时不报告任何错误。而使用 Visual C++ .NET,则可以捕获潜在的错误强制类型转换,并将它标记为错误。开发人员可以通过替换返回类型(用 LRESULT 替换)并重新编译来修复这种潜在的问题。

      • 对在 MFC 应用程序中使用 HTML 帮助提供了增强型支持。

      • DAO 支持:Visual C++ MFC 应用程序向导和 MFC DLL 应用程序向导不再支持 DAO 数据库项目。但是,仍然可以使用“添加类向导”添加从 DAO 派生的类。对于新的本机 C++ 项目,Microsoft 建议使用 OLE DB 或 ODBC。DAO 只用于维护现有的应用程序。

      • 附属 DLL 中本地化资源的增强型支持。

      • 新的使用者宏:用于按名称绑定到数据库中特定列的 COLUMN_NAME* 宏和用于绑定到二进制大对象 (BLOB) 的 BLOB* 宏。

      新增的 64 位数据类型

      若干 OLE DB 模板类中的方法已经被更改为使用新的 64 位数据类型而不是旧的 32 位数据类型。文档已更新以反映这些变化。如果文档和头文件( 示例

      • 由于向导结构已更改,因此以前为“自定义向导”提供的示例已不再使用,并已提供了新的“自定义向导”示例。

      此外,Visual C++ .NET 还包括以下领域的新增示例以及先前版本中提供的示例:

学C语言有很长一段时间了,想做做笔记,把C和C++相关的比较容易忽视的地方记下来,也希望可以给需要的同学一些帮助。

我的这些文章不想对C和C++的语法进行讲解和罗列,这些东西随便找一本书就讲的比我清楚,我只是想把一般人忽视的地方尽自己所能描述一下。权当班门弄斧,贻笑大方了。

首先我想先从C和C++的一些基本概念入手。

稍微学过C和C++的人都知道main()函数市所有C和C++程序必不可少的东西。叫做主函数。所有的程序都应该从main()函数开始执行。但是你们又对这个函数了解多少呢?

我们都知道C和C++是一种函数语言,几乎绝大多数的功能都是通过各种函数的调用来实现的,C和C++也提供了丰富的函数库供编程人员调用。可虽然main()函数每个C程序都必须有的函数,在C或者C++的函数库里却没有叫做main()的函数,它是需要程序设计人员实现的函数。

而且,你们发现了没有,main并不是C和C++的保留字。因此理论上,你可以在其他地方使用main这个名字,比如变量名、类名字、名字空间的名字甚至成员函数的名字。但是,即使这样,你也不能修改main()函数本身的函数名,否则连接器就会报告错误。

main()函数是C和C++程序的入口,这是因为C和C++语言实现会有一个启动函数,比如MS-C++的启动函数就叫做

mainCRTStartup()或者WinMainCRT-Startup()。在这个启动函数的最后会调用main()函数,然后再调用exit()函数结束程序。如果没有main()函数,当然会报错了。所以再C和C++开发环境中main()函数其实是一个回调函数。它是需要我们来实现的。

有些同学可能学过一些应用程序框架,比如MFC什么的。这些程序代码中往往找不到main()函数,这是因为那些应用程序框架把main()函数的实现给隐藏起来了,main()函数在它们这里有固定的实现模式,所以不需要我们编写。在连接阶段,框架会自动将包含main()实现的库加进来连接。

main()函数也是有原型的。这个原型已经是一种标准了,在ISO/IEC14882中对main()的原型进行了定义。


  

上面这两种形式是最具有可移植性的正确写法。当然不同的编译器可能会允许出现一些扩展。比如允许main()返回void,或者有第三个参数char *env[]什么的。这个就要看具体的编译器文档了。

关于返回值,我们知道main()返回的是int类型的。到底返回什么是有不同含义的。一般情况下,返回0,表示程序正常结束,返回任何非0表示错误或非正常退出。前面讲到了,启动函数最后还会调用exit()函数。那么main()函数的返回值就会作为exit()函数的操作数来返回操作系统。

在C++当中对main()函数还有一些特殊的限制。比如:

关于main()函数的参数,它可以让编译好的执行程序具有处理命令行参数的能力。这里需要注意,不要把“命令行参数”和main()函数的“函数实参”混淆,这是两个不同的概念。命令行参数由启动程序截获并打包成字符串数组传递给main()的形参argv[],而包括命令字(也就是执行文件自己的名字)在内的所有参数的个数则被传递给形参argc。试一下吧,咱们来模拟copy命令写个简单的文件拷贝程序。


  

在编写C程序的时候如果没有main()函数,连接器会报错。一般报错信息会提示“unresolved external symbol_main”。这里的"_main"其实就是编译器为main生成的内部名称。其实C和C++语言在编译过程中都会按照特定的规则把用户定义的标识符(函数、变量、类型、名字空间什么的)转换为相应的内部名称。而这些规则还跟指定的连接规范有关。比如,在C语言中,main的内部名称就叫做_main。

C语言这么做,是告诉连接器,这个东西是个函数。实际上,C语言在所有函数的函数名前其实都是加了前缀“_”的,以此来区别函数名和其他标识符名称。

这种规范在C++又是另一种样子。这是因为在C中,所有函数只要不是局部于编译单元(文件作用域)的static函数,就会是具有extern连接类型的和global作用域的全局函数。全局函数是不可以有同名的。但是在C++里面,可以在不同的作用域,比如class,struct,union,namespace中定义同名的函数,甚至在同一个作用域也可以定义同名函数,也就是函数重载。那么转换为内部名称的连接规范就要复杂一些了。比如:


  

在其他地方根据这两个类生成两个实例,并进行操作:


  

这里有四个函数,但是确是同一个名称。编译器应该怎么区分呢?通过各自对象的成员标识符区分?那是在代码中区分的,但是在连接器看来,所有函数其实都是全局函数,而全局函数是不能重名的。所以为了避免二义,在C++中有一个名字修饰规则。也就是在函数名前面添加各级作用域的名称以及重载函数经过编码的参数信息。比如上面四次调用foo函数,其实它们会调用四个具有全局名称的函数,分别是Sample_1_foo@pch@1,Sample_1_foo@int@1,Sample_2_foo@pch@1,Sample_2_foo@int@1。

然而,这种标准并不是强制的,所以不同厂家开发的C++编译器有可能会有些许不同,而这也正是导致不同厂家的C++编译器和连接器不能兼容的原因。

那么好了,当使用不同编程语言联合开发时候,就要定义一个统一的规范,这个规范叫做连接规范。这个很好理解了吧,因为如果同一个标识符在不同编译单元中用不同的连接规范,就会产生不一致的内部名称,连接肯定会失败。

所以,在开发程序库的时候就一定要明确你要用那条连接规范。比如,编写C程序是就要规定C连接规范:extern “C”。大约有这么几种情况:

  • 仅对一个类型、函数、变量或常量指定连接规范;

  
  • 对一段代码限定连接规范

  
  • 当前使用的是C++编译器,并且使用了extern "C"限定了一段代码的连接规范,但又想在其中某行或某段代码保持C++的连接规范。

  
  • 某个声明中指定了某个标识符的连接规范为extern “C”,那么对应的定义也要指定extern “C”:

  

其实如果是面向接口的编程,就不用考虑这么多了。因为即使接口两端的内部名称不同,只要使用了一致的成员对其和排列方式,并遵守一致的调用规范,一致的函数实现方式。也就是C++一致的对象模型,那么基本不会有什么问题的。

在C和C++中,全局变量(extern或static的)存放在程序的静态数据区里面。这些变量在程序进入main()之前就被创建了,并在main()结束后销毁,C和C++提供了一个默认的全局初始化器0。也就是编译器会默认的用0来初始化它们。函数内部的static变量和类的static成员也是在静态存储区,因此也会默认初始化为0。除非你在创建的时候就提供了初值。这是编译器对静态变量的待遇。而对于其他的自动变量,就需要我们给他初始化了。不要指望编译器自动对它们初始化。

所以,全局变量的声明和定义应当放在源文件的开头部位。

变量的初始化和变量的赋值是有区别的。初始化是发生在变量创建的同时,而赋值是在程序中变量创建后干的。
前面说了,对静态存储区的变量(比如全局变量,静态变量什么)的进行初始化是编译器自动进行的,但是局部变量的初始化确实需要编程人员手动进行。

还有,在一个编程单元中,全局变量的初始值不要依赖另一个编译单元的全局变量。什么意思?比如:


  

这两个编译单元编译完成后进行连接,两个全局变量到底先初始化哪个并不确定,连接器也不能保证这一点。先初始化g_x,那g_d也就能顺利初始化,而反之,g_d就不一定是多少了。

另外,C和C++都会有现成的库。就是文件开头包含的那些*.h文件。注意哦,C的库可是有多线程版和单线程版,开发多线程程序应该使用多线程版本的库。另外,在多人开发软件是,库的版本一定要统一。

源代码文件编写的功能有些时运行时起作用,有些编译时就起作用的。这件事需要区分的。比如预编译伪指令、类定义、外部对象声明、函数原型、修饰符号(const,static那些)、类成员访问说明符号(public、private那些)以及连接规范是在编译阶段发挥作用的,可执行程序里是不存在这些东西的。而容器越界访问、虚函数动态决议、动态连接、动态内存分配、异常处理、RTTI这些则是在运行时发挥作用的。比如:


  

这段代码一般在编译阶段没什么问题,但运行时会出错。所以,我们在程序设计时就要对运行的行为有所预见,通过编译连接的程序在运行时不见得正确。

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注脚本之家的更多内容!

我要回帖

更多关于 mfc创建线程的三种方法 的文章

 

随机推荐