c++:谁调用了main/WinMain函数!

非好文不转载!


main和WinMain函数都被操作系统调用!

WinMain函数的四个参数由操作系统传递过来!



我们都听说过一句话:“main是C语言的入口”。我至今不明白为什么这么说。就好像如果有人说:“挣钱是泡妞”,肯定无数砖头拍过来。这句话应该是“挣 钱是泡妞的一个条件,只不过这个条件特别重要”。那么上面那句话应该是 “main是C语言中一个符号,只不过这个符号比较特别。”
    
    我们看下面的例子:   
    
    
    int main(int argc, char* argv)
    {
     return 0;
    }
    
    编译链接它:
    cc test00.c -o test.exe
    会生成 test.exe
    
    但是我们加上这个选项: -nostdlib (不链接标准库)
    cc test00.c -nostdlib -o test.exe
    链接器会报错:
    undefined symbol: __start
    
    也就是说:
    1. 编译器缺省是找 __start 符号,而不是 main
    2. __start 这个符号是程序的起始点
    3. main 是被标准库调用的一个符号
    
    再来思考一个问题:
    我们写程序,比如一个模块,通常要有 initialize 和 de-initialize,但是我们写 C 程序的时候为什么有些模块没有这两个过程么呢?比如我们程序从 main 开始就可以 malloc,free,但是我们在 main 里面却没有初始化堆。再比如在 main 里面可以直接 printf,可是我们并没有打开标准输出文件啊。(不知道什么是 stdin,stdout,stderr 以及 printf 和 stdout 关系的群众请先看看 C 语言中文件的概念)。
    
    有人说,这些东西不需要初始化。如果您真得这么想,请您不要再往下看了,我个人认为计算机软件不适合您。
    
    聪明的人民群众会想,一定是在 main 之前干了些什么。使这些函数可以直接调用而不用初始化。通常,我们会在编译器的环境中找到一个名字类似于 crt0.o 的文件,这个文件中包含了我们刚才所说的 __start 符号。(crt 大概是 C Runtime 的缩写,请大家帮助确认一下。)
    
    那么真正的 crt0.s 是什么样子呢?下面我们给出部分伪代码:
    
    ///
    section .text:
    __start:
    
     :
     init stack;
     init heap;
     open stdin;
     open stdout;
     open stderr;
     :
     push argv;
     push argc;
     call _main; (调用 main)
     :
     destory heap;
     close stdin;
     close stdout;
     close stderr;
     :
     call __exit;
    
    
    实际上可能还有很多初始化工作,因为都是和操作系统相关的,笔者就不一一列出了。
    
    注意:
    1. 不同的编译器,不一定缺省得符号都是 __start。
    2. 汇编里面的 _main 就是 C 语言里面的 main,是因为汇编器和C编译器对符号的命名有差异(通常是差一个下划线'_')。

    3. 目前操作系统结构有两个主要的分支:微内核和宏内核。微内核的优点是,结构清晰,简单,内核组件较少,便于维护;缺点是,进程间通信较多,程序频繁进出内 核,效率较低。宏内核正好相反。我说这个是什么目的是:没办法保证每个组件都在用户空间(标准库函数)中初始化,有些组件确实可能不要初始化,操作系统在 创建进程的时候在内核空间做的。这依赖于操作系统的具体实现,比如堆,宏内核结构可能在内核初始化,微内核结构在用户空间;即使同样是微内核,这个东东也 可能会被拿到内核空间初始化。



  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Visual C++ 2005入门经典.pdf(整理并添加所有书签) ,看书的时候更方便. 封面 目录 第1章 使用Visual C++ 2005 编程 1.1 .NET Framework 1.2 CLR 1.3 编写C++应用程序 1.4 学习windows编程 1.4.1 学习c++ 1.4.2 C++标准 1.4.3 控制台应用程序 1.4.4 Windows编程概念 1.5 集成开发环境简介 1.6 使用IDE 1.6.1 工具栏选项 1.6.2 可停靠的工具栏 1.6.3 文档 1.6.4 项目和解决方案 1.6.5 设置Visual C++2005的选项 1.6.6 创建和执行windows应用程序 1.6.7 创建windows Forms应用程序 1.7 小结 第2章 数据、变量和计算 2.1 C++程序结构 2.1.1 程序注释 2.1.2 #include指令——头文件 2.1.3 命名空间和using声明 2.1.4 main()函数 2.1.5 程序语句 2.1.6 空白 2.1.7 语句块 2.1.8 自动生成的控制台程序 2.2 定义变量 2.2.1 命名变量 2.2.2 C++中的关键字 2.2.3 声明变量 2.2.4 变量的初值 2.3 基本数据类型 2.3.1 整型变量 2.3.2 字符数据类型 2.3.3 整型修饰符 2.3.4 布尔类型 2.3.5 浮点类型 2.3.6 ISO/ANSI C++中的基本类型 2.3.7 字面值 2.3.8 定义数据类型的同义词 2.3.9 具有特定值集的变量 2.3.10 指定枚举常量的类型 2.4 基本的输入输出操作 2.4.1 从键盘输入 2.4.2 到命令行的输出 2.4.3 格式化输出 2.4.4 转义序列 2.5 C++中的计算 2.5.1 赋值语句 2.5.2 算术运算 2.5.3 计算余数 2.5.4 修改变量 2.5.5 增量和减量运算符 2.5.6 计算的顺序 2.6 变量类型和类型强制转换 2.6.1 对操作数进行类型强制转换的规则 2.6.2 赋值语句中的类型强制转换 2.6.3 显式类型强制转换 2.6.4 老式的类型强制转换 2.6.5 按位运算符 2.7 了解存储时间和作用域 2.7.1 自动变量 2.7.2 决定变量声明的位置 2.7.3 全局娈量 2.7.4 静态变量 2.8 命名空间 2.8.1 声明命名空间 2.8.2 多个命名空间 2.9 C++/CLI编程 2.9.1 C++/CLI特有的基本数据类型 2.9.2 命令行上的C++/CLI输出 2.9.3 C++/CLI特有的功能——格式化输出 2.9.4 C++/CLI的键盘输入 2.9.5 使用safe cast 2.9.6 C++/CLI枚举 2.10 小结 2.11 练习题 第3章 判断和循环 3.1 比较数据值 3.1.1 if语句 3.1.2 嵌套if语句 3.1.3 扩展的if语句 3.1.4 嵌套的if-else语句 3.1.5 逻辑运算符和表达式 3.1.6 条件运算符 3.1.7 switch语句 3.1.8 无条件转移 3.2 重复执行语句块 3.2.1 循环的概念 3.2.2 for循环的变体 3.2.3 while循环 3.2.4 do-while循环 3.2.5 嵌套的循环 3.3 C++/CLI编程 3.4 小结 3.5 练习 第4章 数组、字符串和指针 4.1 处理多个相同类型的数据值 4.1.1 数组 4.1.2 声明数组 4.1.3 初始化数组 4.1.4 字符数组和字符串处理 4.1.5 多维数组 4.2 间接数据存取 4.2.1 指针的概念 4.2.2 声明指针 4.2.3 使用指针 4.2.4 初始化指针 4.2.5 sizeof运算符 4.2.6 常量指针和指向常量的指针 4.2.7指针和数组 4.3 动态内存分配 4.3.1 堆的别名——自由存储器 4.3.2 new和delete运算符 4.3.3 为数组动态分配内存 4.3.4 多维数组的动态分配 4.4 使用引用 4.4.1 引用的概念 4.4.2 声明并初始化引用 4.5 C++/CLI编程 4.5.1 跟踪句柄 4.5.2 CLR数组 4.5.3 字符串 4.5.4 跟踪引用 4.5.5 内部指针 4.6 小结 4.7 练习 第5章 程序结构(1) 5.1 理解函数 5.1.1 需要函数的原因 5.1.2 函数的结构 5.1.3 使用函数 5.2 给函数传递实参 5.2.1 按值传递机制 5.2.2 给函数传递指针实参 5.2.3 给函数传递数组 5.2.4 给函数传递引用实参 5.2.5 使用const修饰符 5.2.6 main()函数的实参 5.2.7 接受数量不定的函数实参 5.3 从函数返回值 5.3.1 返回指针 5.3.2 返回引用 5.3.3 函数中的静态变量 5.4 递归函数调用 5.5 C++/CLI编程 5.5.1 接受数量可变实参的函数 5.5.2 main()的实参 5.6 小结 5.7 练习 第6章 程序结构(2) 6.1 函数指针 6.1.1 声明函数指针 6.1.2 函数指针作为实参 6.1.3 函数指针的数组 6.2 初始化函数形参 6.3 异常 6.3.1 抛出异常 6.3.2 捕获异常 6.3.3 MFC中的异常处理 6.4 处理内存分配错误 6.5 函数重载 6.5.1 函数重载的概念 6.5.2 何时重载函数 6.6 函数模板 6.7 使用函数的示例 6.7.1 实现计算器 6.7.2 从字符串中删除空格 6.7.3 计算表达式的值 6.7.4 获得项值 6.7.5 分析数 6.7.6 整合程序 6.7.7 扩展程序 6.7.8 提取子字符串 6.7.9 运行修改过的程序 6.8 C++/CLI编程 6.8.1 理解类函数 6.8.2 CLR版本的计算器程序 6.9 小结 6.10 练习 第7章 自定义数据类型 7.1 C++中的结构 7.1.1 结构的概念 7.1.2 定义结构 7.1.3 初始化结构 7.1.4 访问结构的成员 7.1.5 伴随结构的智能帮助 7.1.6 RECT结构 7.1.7 使用指针处理结构 7.2 数据类型、对象、类和实例 7.2.1 类的起源 7.2.2 类的操作 7.2.3 术语 7.3 理解类 7.3.1 定义类 7.3.2 声明类的对象 7.3.3 访问类的数据成员 7.3.4 类的成员函数 7.3.5 成员函数定义的位置 7.3.6 内联函数 7.4 类构造函数 7.4.1 构造函数的概念 7.4.2 默认的构造函数 7 4.3 在类定义中指定默认的形参值 7.4.4 在构造函数中使用初始化列表 7.5 类的私有成员 7.5.1 访问私有类成员 7.5.2 类的友元函数 7.5.3 默认复制构造函数 7.6 this指针 7.7 类的const对象 7.7.1 类的const成员函数 7.7.2 类外部的成员函数定义 7.8 类对象的数组 7.9 类的静态成员 7.9.1 类的静态数据成员 7.9.2 类的静态函数成员 7.10 类对象的指针和引用 7.10.1 类对象的指针 7.10.2 类对象的引用 7.11 C++/CLI编程 7.11.1 定义数值类类型 7.11.2 定义引用类类型 7.11.3 类属性 7.11.4 initonly字段 7.11.5 静态构造函数 7.12 小结 7.13 练习 第8章 深入理解类 8.1 类的析构函数 8.1.1 析构函数的概念 8.1.2 默认的析构函数 8.1.3 析构函数与动态内存分配 8.2 实现复制构造函数 8.3 在变量之间共享内存 8.3.1 定义联台 8.3.2 匿名联合 8.3.3 类和结构中的联合 8.4 运算符重载 8.4.1 实现重载的运算符 8.4.2 实现对运算符的完全支持 8.4.3 重载赋值运算符 8.4.4 重载加法运算符 8.4.5 重载递增和递减运算符 8.5 类模板 8.5.1 定义类模板 8.5.2 根据类模板创建对象 8.5.3 使用有多个形参的类模板 8.6 使用类 8.6.1 类接口的概念 8.6.2 定义问题 8.6.3 实现CBox类 8.6.4 定义CBox类 8.6.5 使用CBox类 8.7 组织程序代码 8.8 C++/CLI编程 8.8.1 在数值类中重载运算符 8.8.2 重载递增和递减运算符 8.8.3 在引用类中重载运算符 8.9 小结 8.1O 练习 第9章 类继承和虚函数 9.1 面向对象编程的基本思想 9.2 类的继承 9.2.1 基类的概念 9.2.2 基类的派生类 9.3 继承机制下的访问控制 9.3.1 派生类中构造函数的操作 9.3.2 声明类的保护成员 9.3.3 继承类成员的访问级别 9.4 派生类中的复制构造函数 9.5 友元类成员 9.5.1 友元类 9.5.2 对类友元关系的限制 9.6 虚函数 9.6.1 虚函数的概念 9.6.2 使用指向类对象的指针 9.6.3 使用引用处理虚函数 9.6.4 纯虚函数 9.6.5 抽象类 9.6.6 间接基类 9.6.7 虚析构函数 9.7 类类型之间的强制转换 9.8 嵌套类 9.9 C++/CLI编程 9.9.1 C++/CLI类的继承 9.9.2 接口类 9.9.3 定义接口类 9.9.4 类和程序集 9.9.5 被指定为new的函数 9.9.6 委托和事件 9.9.7 引用类的析构函数和结束函数 9.9.8 通用类 9.10 小结 9.11 练习 第10章 调试技术 10.1 理解调试 10.1.1 程序故障 10.1.2 常见故障 10.2 基本的调试操作 10.2.1 设置断点 10.2.2 设置跟踪点 10.2.3 启动调试模式 10.2.4 修改变量的值 10.3 添加调试代码 10.3.1 使用断言 10.3.2 添加自己的调试代码 10.4 调试程序 10.4.1 调用堆栈 10.4.2 单步执行到出错位置 10.5 测试扩展的类 10.6 调试动态内存 10.6.1 检查自由存储器的函数 10.6.2 控制自由存储器的调试操作 10.6.3 自由存储器的调试输出 10.7 调试C++/CLI程序 10.8 小结 第11章 Windows编程的概念 11.1 Windows编程基础 11.1.1窗口的元素 11.1.2 Windows程序与操作系统 11.1.3事件驱动型程序 11.1.4 Windows消息 11.1.5 WindowsAPI 11.1.6.Windows数据类型 11.1.7 Windows程序中的符号 11.2 Windows程序的结构 11.2.1 WinMain()函数 11.2.2消息处理函数 11.2.3简单的Windows程序 11.3 Windows程序的组织 11.4 MFC 11.4.1 MFC标记法 11.4.2 MFC程序的组织方式 11.5使用Windows Forms 11.6小结 第12章 使用MFC编写Windows程序 12.1 MFC的文档,视图概念 12.1.1 文档的概念 12.1.2 文档界面 12.1.3 视图的概念 12.1.4 连接文档和视图 12.1.5 应用程序和MFC 12.2 创建MFC应用程序 12.2.1 创建SDI应用程序 12.2.2 MFCApplicationwizard的输出 12.2.3 创建MDI应用程序 12.3 小结 12.4 练习 第13章 处理菜单和工具栏 13.1 与Windows进行通信 13.1.1 了解消息映射 13.1.2 消息类别 13.1.3 处理程序中的消息 13.2 扩充Sketcher程序 13.3 菜单的元素 13.4 为菜单消息添加处理程序 13.4.1 选择处理菜单消息的类 13.4.2 创建菜单消息函数 13.4.3 编写菜单消息函数的代码 13.4.4 添加更新用户界面的消息处理程序 13.5 添加工具栏按钮 13.5.1 编辑工具栏按钮的属性 13.5.2 练习使用工具栏按钮 13.5.3 添加工具提示 13.6 小结 13.7 练习题 第14章 在窗口中绘图 14.1 窗口绘图的基础知识 14.1.1 窗口客户区 14.1.2 Windows图形设备界面 14.2 Visual C++中的绘图机制 14.2.1 应用程序中的视图类 14.2.2 CDC类 14.3 实际绘制图形 14.4 对鼠标进行编程 14.4.1 鼠标发出的消息 14.4.2 鼠标消息处理程序 14.4.3 使用鼠标绘图 14.5 练习使用Sketcher程序 14.5.1 运行这个示例 14.5.2 捕获鼠标消息 14.6 小结 14.7 练习题 第15章 创建文档和改进视图 15.1 什么是集合类 15.1.1 集合的类型 15.1.2 类型安全的集合类 15.1.3 对象集合 15.1.4 类型化指针集合 15.2 使用CList模板类 15.2.1 绘制曲线 15.2.2 定义CCurve类 15.2.3 实现CCurve类 15.2.4 练习使用CCurve类 15.3 创建文档 15.4 改进视图 15.4.1 更新多个视图 15.4.2 滚动视图 15.4.3 使用MM_LOENGLISH映射模式 15.5 删除和移动形状 15.6 实现上下文菜单 15.6.1 关联菜单和类 15.6.2 选择上下文菜单 15.6.3 醒目显示元素 15.6.4 处理菜单消息 15.7 处理被屏蔽的元素 15.8 小结 15.9 练习 第16章 使用对话框和控件 16.1 理解对话框 16.2 理解控件 16.3 创建对话框资源 16.4 对话框的编程 16.4.1 添加对话框类 16.4.2 模态和非模态对话框 16.4.3 显示对话框 16.5 支持对话框控件 16.5.1 初始化控件 16.5.2 处理单选按钮消息 16.6 完成对话框的操作 16.6.1 给文档类添加存储线宽的成员 16.6.2 给元素添加线宽 16.6.3 在视图中创建元素 16.6.4 练习使用对话框 16.7 使用微调按钮控件 16.7.1 添加Scale菜单项和工具栏按钮 16.7.2 创建微调按钮 16.7.3 生成比例对话框类 16.7.4 显示微调按钮 16.8 使用比例系数 16.8.1 可缩放的映射模式 16.8.2 设置文档的大小 16.8.3 设置映射模式 16.8.4 同时实现滚动与缩放 16.9 使用状态栏 16.10 使用列表框 16.10.1 删除比例对话框 16.1O.2 创建列表框控件 16.11 使用编辑框控件 16.11.1 创建编辑框资源 16.11.2 创建对话框类 16.11.3 添加Text菜单项 16.11.4 定义文本元素 16.11.5 实现CText类 16.11.6 创建文本元素 16.12 小结 16.13 练习 第17章 存储和打印文档 17.1 了解串行化 17.2 串行化文档 17.2.1 文档类定义中的串行化 17.2.2 丈档类实现中的串行化 17.2.3 基于CObject的类的功能 17.2.4 串行化的工作方式 17.2.5 如何实现类的串行化 17.3 应用串行化 17.3.1 记录文档修改 17.3.2 串行化文档 17.3.3 串行化元素类 17.4 练习串行化 17.5 移动文本 17.6 打印文档 17.7 实现多页打印 17.7.1 获取文档的总尺寸 17.7.2 存储打印数据 17.7.3 准备打印 17.7.4 打印后的清除 17.7.5 准备设备上下文 17.7.6 打印文档 17.7.7 获得文档的打印输出 17.8 小结 17.9 练习题 第18章 编写自己的DLL 18.1 了解DLL 18.1.1 DLL的工作方式 18.1.2 DLL的内容 18.1.3 DLL变体 18.2 决定放入DLL的内容 18.3 编写DLL 18.3.1 编写和使用扩展DLL 18.3.2 从DLL中导出变量和函数 18.3.3 将符号导入程序 18.3.4 实现符号从DLL的导出 18.4 小结 18.5 练习题 第19章 连接到数据源 19.1 数据库基础知识 19.2 SQL 19.2.1 使用SQL检索数据 19.2.2 使用SQL连接表 19.2.3 对记录进行排序 19.3 MFC中的数据库支持 19.4 创建数据库应用程序 19.4.1 注册ODBC数据库 19.4.2 生成MFC ODBC程序 19.4.3 了解程序结构 19.4.4 示例练习 19.5 对记录集进行排序 19.6 使用另一个记录集对象 19.6.1 添加记录集类 19.6.2 添加记录集的视图类 19.6.3 定制记录集 19.6.4 访问多个表视图 19.6.5 查看产品的订单 19.7 查看客户的详细情况 19.7.1 添加客户记录集 19.7.2 创建客户对话框资源 19.7.3 创建客户视图类 19.7.4 添加过滤器 19.7.5 实现过滤器参数 19.7.6 链接订单对话框和客户对话框 19.7.7 练习使用数据库查看器 19.8 小结 19.9 练习题 第20章 更新数据源 20.1 更新操作 20.1.1 CRecordset更新操作 20.1.2 事务 20.2 简单的更新示例 20.3 管理更新过程 20.4 向表中添加行 20.4.1 订单录入过程 20.4.2 创建资源 20.4.3 创建记录集 20.4.4 创建记录集视图 20.4.5 给对话框资源添加控件 20.4.6 实现对话框切换 20.4.7 创建订单ID 20.4.8 存储订单数据 20.4.9 为订单选择产品 20.4.10 添加新订单 20.5 小结 20.6 练习 第21章 使用Windows Forms的应用程序 21.1 理解Wqndows Forms 21.2 理解Windows Forms应用程序 21.2.1 修改窗体的属性 21.2.2 如何启动应用程序 21.3 定制应用程序GUI 21.3.1 给窗体添加控件 21.3.2 添加选项卡控件 21.3.3 使用CroupBox控件 21.3.4 使用Button控件 21.3.5 使用WebBrowser控件 21.3.6 Winning应用程序的操作 21.3.7 添加上下文菜单 21.3.8 创建事件处理程序 21.3.9 处理Limits菜单的事件 21.3.10 创建对话框 21.3.11 使用对话框 21.3.12 添加第二个对话框 21.3.13 实现Help|About菜单项 21.3.14 处理按钮单击事件 21.3.15 响应上下文莱单 21.4 小结 21.5 练习 第22章 在Windows Forms应用程序中访问数据源 22.1 使用数据源 22.2 访问并显示数据 22.3 使用DataGridView控件 22.4 在无约束模式中使用DataGridView控件 22.5 定制DataGridView控件 22.5.1 定制题头单元格 22.5.2 定制非题头单元格 22.5.3 动态设置单元格样式 22.6 使用约束模式 22.7 BindingSource组件 22.8 使用BindingNavigator控件 22.9 绑定到单独的控件 22.10 使用多个表 22.11 小结 22.12 练习 附录A C++关键字 A1 ISO/ANSI C++关键宇 A2 C++/CLI关键字 附录B ASCII码
C++面试题 参考:http://blog.csdn.net/Ghost90/archive/2009/04/22/4099672.aspx 整理:松鼠 时间:2009-5-8 1、const 有什么用途?(请至少说明两种) 答: (1)可以定义 const 常量 (2)const可以修饰函数的参数、返回值,甚至函数的定义体。被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。 2、在C++ 程序中调用被 C编译器编译后的函数,为什么要加 extern “C”? 答:C++语言支持函数重载,C语言不支持函数重载。函数C++编译后在库中的名字与C语言的不同。假设某个函数的原型为: void foo(int x, int y); 该函数被C编译器编译后在库中的名字为_foo,而C++编译器则会产生像_foo_int_int之类的名字。 C++提供了C连接交换指定符号extern“C”来解决名字匹配问题。 3、请简述以下两个for循环的优缺点(5分) for (i=0; i<N; i++) { if (condition) DoSomething(); else DoOtherthing(); } if (condition) { for (i=0; i<N; i++) DoSomething(); } else { for (i=0; i<N; i++) DoOtherthing(); } 优点:程序简洁 缺点:多执行了N-1次逻辑判断,并且打断了循环“流水线”作业,使得编译器不能对循环进行优化处理,降低了效率。 优点:循环的效率高 缺点:程序不简洁 4、有关内存的思考题 void GetMemory(char *p) { p = (char *)malloc(100); } void Test(void) { char *str = NULL; GetMemory(str); strcpy(str, "hello world"); printf(str); } 请问运行Test函数会有什么样的结果? 答:程序崩溃。 因为GetMemory并不能传递动态内存, Test函数中的 str一直都是 NULL。 strcpy(str, "hello world");将使程序崩溃。 char *GetMemory(void) { char p[] = "hello world"; return p; } void Test(void) { char *str = NULL; str = GetMemory(); printf(str); } 请问运行Test函数会有什么样的结果? 答:可能是乱码。 因为GetMemory返回的是指向“栈内存”的指针,该指针的地址不是 NULL,但其原现的内容已经被清除,新内容不可知。 void GetMemory2(char **p, int num) { *p = (char *)malloc(num); } void Test(void) { char *str = NULL; GetMemory(&str, 100); strcpy(str, "hello"); printf(str); } 请问运行Test函数会有什么样的结果? 答: (1)能够输出hello (2)内存泄漏 void Test(void) { char *str = (char *) malloc(100); strcpy(str, “hello”); free(str); if(str != NULL) { strcpy(str, “world”); printf(str); } } 请问运行Test函数会有什么样的结果? 答:篡改动态内存区的内容,后果难以预料,非常危险。 因为free(str);之后,str成为野指针, if(str != NULL)语句不起作用。 5、编写strcpy函数(10分) 已知strcpy函数的原型是 char *strcpy(char *strDest, const char *strSrc); 其中strDest是目的字符串,strSrc是源字符串。 (1)不调用C++/C的字符串库函数,请编写函数 strcpy char *strcpy(char* strDest, const char* strSrc) { assert((strDest!=NULL) && (strSrc !=NULL));//2分 char *address = strDest;//2分 while( (*strDest++ = * strSrc++) != ‘\0’ )//2分 NULL; return address;// 2分 } 5.1 strcpy能把strSrc的内容复制到strDest,为什么还要char * 类型的返回值? 答:为了实现链式表达式。 // 2分 例如int length = strlen( strcpy( strDest, "hello world") ); 6、编写类String的构造函数、析构函数和赋值函数(25分) 已知类String的原型为: class String { public: String(const char *str = NULL);//普通构造函数 String(const String &other);//拷贝构造函数 ~ String(void);// 析构函数 String & operate =(const String &other);// 赋值函数 private: char* m_data;// 用于保存字符串 }; 请编写String的上述4个函数。 标准答案: // String的析构函数 String::~String(void) // 3分 { delete [] m_data; // 由于m_data是内部数据类型,也可以写成delete m_data; } // String的普通构造函数 String::String(const char *str) // 6分 { if(str==NULL) { m_data = new char[1]; // 若能加NULL 判断则更好 *m_data = ‘\0’; } else { int length = strlen(str); m_data = new char[length+1]; // 若能加NULL 判断则更好 strcpy(m_data, str); } } // 拷贝构造函数 String::String(const String &other) // 3分 { int length = strlen(other.m_data); m_data = new char[length+1]; // 若能加NULL 判断则更好 strcpy(m_data, other.m_data); } // 赋值函数 String & String::operate =(const String &other) // 13分 { // (1) 检查自赋值 // 4分 if(this == &other) return *this; // (2) 释放原有的内存资源 // 3分 delete [] m_data; // ()分配新的内存资源,并复制内容// 3分 int length = strlen(other.m_data); m_data = new char[length+1]; // 若能加NULL 判断则更好 strcpy(m_data, other.m_data); // ()返回本对象的引用 // 3分 return *this; } 7、实现双向链表删除一个节点P,在节点P后插入一个节点,写出这两个函数。 void DeleteNode(DuNode *p) { p->prior->next=p->next; p->next->prior=p->prior; } void InsertNode(DuNode *p, DuNode *s)//Node "s" is inserted after "p" { s->next=p->next; p->next->prior=s; p->next=s; s->prior=p; } 8、Windows程序的入口是哪里?写出Windows消息机制的流程。 WINDOWS入口是WinMain函数 消息机制的流程: 系统中发生了某个事件 Windows把这个事件翻译为消息,然后把它放到消息队列中 1. 应用程序从消息队列中接收到这个消息,把它存放在TMsg记录中 2. 应用程序把消息传递给一个适当的窗口的窗口过程 3. 窗口过程响应这个消息并进行处理 9.写一个函数,将其中的\t都转换成4个空格。 #include<iostream> using namespace std; char* Convert_t(char *des,char *src) { char *temp; des=new char[100]; temp=des; while(*src!='\0') { if(*src=='\t') { src++; *des++=' '; *des++=' '; *des++=' '; *des++=' '; continue; } *des++=*src++; } *des='\0'; des=temp; return des; } int main() { char *t="asdf\tasd\tasasddas\\tdfasdf",*d; cout<<t<<endl; cout<<Convert_t(d,t); getchar(); } 10.如何定义和实现一个类的成员函数为回调函数? 如果类的成员函数是一个callback函数, 必须宣告它为"static",才能把C++ 编译器加诸于函数的一个隐藏参数this去掉。 11.C++里面是不是所有的动作都是main()引起的?如果不是,请举例。 不是的,C++里面有些动作不是引起的,比如,全局对象的实例化、全局变量的动态空间申请,等等 下面是一个例子: #include<iostream> using namespace std; char *des=new char[100]; //全局变量的动态空间申请在程序运行之后,main运行之前完成。所以不是所有的动作都是main引起的。 int main() { char *des="abc"; cout<<des<<endl; getchar(); } 12.C++里面如何声明const void f(void)函数为C程序中的库函数? extern "C" const void f(void); 这样声明之后,相当于告诉C, 函数const void f(void)是在C++语言的文件中声明或者实现的,c程序可以使用这个C++中的函数了,从而实现C++和c的混合编程。 13、编写一个函数,作用是把一个char组成的字符串循环右移n个。比如原来是“abcdefghi”如果n=2,移位后应该是“hiabcdefgh” 正确解答1: void LoopMove(char* pStr, int steps) { int n = strlen( pStr ) - steps; char tmp[MAX_LEN]; strcpy ( tmp, pStr + n ); strcpy ( tmp + steps, pStr); *( tmp + strlen ( pStr ) ) = '\0'; strcpy( pStr, tmp ); } 正确解答2: void LoopMove(char* pStr,int steps ) { int n = strlen( pStr ) - steps; char tmp[MAX_LEN]; memcpy( tmp, pStr + n, steps ); memcpy(pStr + steps, pStr, n ); memcpy(pStr, tmp, steps ); } 14、写出输出结果 void fun(char s[10]) { char a[10]; cout<<"a:"<<sizeof(a)<<endl; cout<<"s:"<<sizeof(s)<<endl; } 输出: a:10 s:4 15、内存的分配方式的分配方式有几种? 答: 1. 从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量。 2. 在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。 3. 从堆上分配,亦称动态内存分配。程序在运行的时候用malloc或new申请任意多少的内存,程序员自己负责在何时用free或delete释放内存。动态内存的生存期由我们决定,使用非常灵活,但问题也最多。 16.是不是一个父类写了一个virtual 函数,如果子类覆盖它的函数不加virtual ,也能实现多态? 答:virtual修饰符会被隐形继承的。private 也被集成,只事派生类没有访问权限而已。virtual可加可不加。子类的空间里有父类的所有变量(static除外)。同一个函数只存在一个实体(inline除外)。子类覆盖它的函数不加virtual ,也能实现多态。在子类的空间里,有父类的私有变量。私有变量不能直接访问。 17.进程间通信的方式有? 进程间通信的方式有 共享内存, 管道 ,Socket ,消息队列 , DDE等 18.C++中什么数据分配在栈或堆中,New分配数据是在近堆还是远堆中? 答:栈: 存放局部变量,函数调用参数,函数返回值,函数返回地址。由系统管理 堆: 程序运行时动态申请,new 和 malloc申请的内存就在堆上 (Google搜):DOS下程序是独占方式,堆分为近堆和远堆,近堆和栈是在数据段开辟的同一块内存地址,栈从下往上增长,堆从上向下分配,中间没有规定分界线,所以程序控制不当,如深层次的递归,大量的动态地址分配很容易造成堆栈冲突,即堆栈地址重叠,从而造成死机和程序运行异常。堆和栈连在一起说的原因就是如此。至于远堆则是指在数据段和代码段以外计算机所有没有使用的剩余基本内存。Windows采用的是虚拟地址,内存分配方式就不一样了 补充:DOS下堆栈的分配是由程序而不是操作系统自己控制的,具体分配大小、方式随编译系统、程序模式不同而异。C语言的堆栈分配代码在启动代码中. 19.全局变量和局部变量在内存中是否有区别?如果有,是什么区别? 全局变量储存在静态数据库,局部变量在堆栈。 20.TCP/IP 建立连接的过程?(3-way shake) 答:在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接。 第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认; 第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态; 第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。 21.winsock建立连接的主要实现步骤? 答:服务器端:socker()建立套接字,绑定(bind)并监听(listen),用accept()等待客户端连接。 客户端:socker()建立套接字,连接(connect)服务器,连接上后使用send()和recv(),在套接字上写读数据,直至数据交换完毕,closesocket()关闭套接字。 服务器端:accept()发现有客户端连接,建立一个新的套接字,自身重新开始等待连接。该新产生的套接字使用send()和recv()写读数据,直至数据交换完毕,closesocket()关闭套接字。 22.static有什么用途?(请至少说明两种) 1) 在函数体,一个被声明为静态的变量在这一函数调用过程中维持其值不变。 2) 在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所用函数访问,但不能被模块外其它函数访问。它是一个本地的全局变量。 3) 在模块内,一个被声明为静态的函数只可被这一模块内的其它函数调用。那就是,这个函数被限制在声明它的模块的本地范围内使用 23.引用与指针有什么区别? 1) 引用必须被初始化,指针不必。 2) 引用初始化以后不能被改变,指针可以改变所指的对象。 3) 不存在指向空值的引用,但是存在指向空值的指针。 24、请写出下列代码的输出内容 #include<stdio.h> main() { int a,b,c,d; a=10; b=a++; c=++a; d=10*a++; printf("b,c,d:%d,%d,%d",b,c,d); return 0; } 答:10,12,120 main() { int a[5]={1,2,3,4,5}; int *ptr=(int *)(&a+1); printf("%d,%d",*(a+1),*(ptr-1)); } 输出:2,5 *(a+1)就是a[1],*(ptr-1)就是a[4],执行结果是2,5 &a+1不是首地址+1,系统会认为加一个a数组的偏移,是偏移了一个数组的大小(本例是5个int) int *ptr=(int *)(&a+1); 则ptr实际是&(a[5]),也就是a+5 原因如下: &a是数组指针,其类型为 int (*)[5]; 而指针加1要根据指针类型加上一定的值, 不同类型的指针+1之后增加的大小不同 a是长度为5的int数组指针,所以要加 5*sizeof(int) 所以ptr实际是a[5] 但是prt与(&a+1)类型是不一样的(这点很重要) 所以prt-1只会减去sizeof(int*) a,&a的地址是一样的,但意思不一样,a是数组首地址,也就是a[0]的地址,&a是对象(数组)首地址,a+1是数组下一元素的地址,即a[1],&a+1是下一个对象的地址,即a[5]
Visual C++ 2005入门经典.pdf(整理并添加所有书签) ,看书的时候更方便. 封面 目录 第1章 使用Visual C++ 2005 编程 1.1 .NET Framework 1.2 CLR 1.3 编写C++应用程序 1.4 学习windows编程 1.4.1 学习c++ 1.4.2 C++标准 1.4.3 控制台应用程序 1.4.4 Windows编程概念 1.5 集成开发环境简介 1.6 使用IDE 1.6.1 工具栏选项 1.6.2 可停靠的工具栏 1.6.3 文档 1.6.4 项目和解决方案 1.6.5 设置Visual C++2005的选项 1.6.6 创建和执行windows应用程序 1.6.7 创建windows Forms应用程序 1.7 小结 第2章 数据、变量和计算 2.1 C++程序结构 2.1.1 程序注释 2.1.2 #include指令——头文件 2.1.3 命名空间和using声明 2.1.4 main()函数 2.1.5 程序语句 2.1.6 空白 2.1.7 语句块 2.1.8 自动生成的控制台程序 2.2 定义变量 2.2.1 命名变量 2.2.2 C++中的关键字 2.2.3 声明变量 2.2.4 变量的初值 2.3 基本数据类型 2.3.1 整型变量 2.3.2 字符数据类型 2.3.3 整型修饰符 2.3.4 布尔类型 2.3.5 浮点类型 2.3.6 ISO/ANSI C++中的基本类型 2.3.7 字面值 2.3.8 定义数据类型的同义词 2.3.9 具有特定值集的变量 2.3.10 指定枚举常量的类型 2.4 基本的输入输出操作 2.4.1 从键盘输入 2.4.2 到命令行的输出 2.4.3 格式化输出 2.4.4 转义序列 2.5 C++中的计算 2.5.1 赋值语句 2.5.2 算术运算 2.5.3 计算余数 2.5.4 修改变量 2.5.5 增量和减量运算符 2.5.6 计算的顺序 2.6 变量类型和类型强制转换 2.6.1 对操作数进行类型强制转换的规则 2.6.2 赋值语句中的类型强制转换 2.6.3 显式类型强制转换 2.6.4 老式的类型强制转换 2.6.5 按位运算符 2.7 了解存储时间和作用域 2.7.1 自动变量 2.7.2 决定变量声明的位置 2.7.3 全局娈量 2.7.4 静态变量 2.8 命名空间 2.8.1 声明命名空间 2.8.2 多个命名空间 2.9 C++/CLI编程 2.9.1 C++/CLI特有的基本数据类型 2.9.2 命令行上的C++/CLI输出 2.9.3 C++/CLI特有的功能——格式化输出 2.9.4 C++/CLI的键盘输入 2.9.5 使用safe cast 2.9.6 C++/CLI枚举 2.10 小结 2.11 练习题 第3章 判断和循环 3.1 比较数据值 3.1.1 if语句 3.1.2 嵌套if语句 3.1.3 扩展的if语句 3.1.4 嵌套的if-else语句 3.1.5 逻辑运算符和表达式 3.1.6 条件运算符 3.1.7 switch语句 3.1.8 无条件转移 3.2 重复执行语句块 3.2.1 循环的概念 3.2.2 for循环的变体 3.2.3 while循环 3.2.4 do-while循环 3.2.5 嵌套的循环 3.3 C++/CLI编程 3.4 小结 3.5 练习 第4章 数组、字符串和指针 4.1 处理多个相同类型的数据值 4.1.1 数组 4.1.2 声明数组 4.1.3 初始化数组 4.1.4 字符数组和字符串处理 4.1.5 多维数组 4.2 间接数据存取 4.2.1 指针的概念 4.2.2 声明指针 4.2.3 使用指针 4.2.4 初始化指针 4.2.5 sizeof运算符 4.2.6 常量指针和指向常量的指针 4.2.7指针和数组 4.3 动态内存分配 4.3.1 堆的别名——自由存储器 4.3.2 new和delete运算符 4.3.3 为数组动态分配内存 4.3.4 多维数组的动态分配 4.4 使用引用 4.4.1 引用的概念 4.4.2 声明并初始化引用 4.5 C++/CLI编程 4.5.1 跟踪句柄 4.5.2 CLR数组 4.5.3 字符串 4.5.4 跟踪引用 4.5.5 内部指针 4.6 小结 4.7 练习 第5章 程序结构(1) 5.1 理解函数 5.1.1 需要函数的原因 5.1.2 函数的结构 5.1.3 使用函数 5.2 给函数传递实参 5.2.1 按值传递机制 5.2.2 给函数传递指针实参 5.2.3 给函数传递数组 5.2.4 给函数传递引用实参 5.2.5 使用const修饰符 5.2.6 main()函数的实参 5.2.7 接受数量不定的函数实参 5.3 从函数返回值 5.3.1 返回指针 5.3.2 返回引用 5.3.3 函数中的静态变量 5.4 递归函数调用 5.5 C++/CLI编程 5.5.1 接受数量可变实参的函数 5.5.2 main()的实参 5.6 小结 5.7 练习 第6章 程序结构(2) 6.1 函数指针 6.1.1 声明函数指针 6.1.2 函数指针作为实参 6.1.3 函数指针的数组 6.2 初始化函数形参 6.3 异常 6.3.1 抛出异常 6.3.2 捕获异常 6.3.3 MFC中的异常处理 6.4 处理内存分配错误 6.5 函数重载 6.5.1 函数重载的概念 6.5.2 何时重载函数 6.6 函数模板 6.7 使用函数的示例 6.7.1 实现计算器 6.7.2 从字符串中删除空格 6.7.3 计算表达式的值 6.7.4 获得项值 6.7.5 分析数 6.7.6 整合程序 6.7.7 扩展程序 6.7.8 提取子字符串 6.7.9 运行修改过的程序 6.8 C++/CLI编程 6.8.1 理解类函数 6.8.2 CLR版本的计算器程序 6.9 小结 6.10 练习 第7章 自定义数据类型 7.1 C++中的结构 7.1.1 结构的概念 7.1.2 定义结构 7.1.3 初始化结构 7.1.4 访问结构的成员 7.1.5 伴随结构的智能帮助 7.1.6 RECT结构 7.1.7 使用指针处理结构 7.2 数据类型、对象、类和实例 7.2.1 类的起源 7.2.2 类的操作 7.2.3 术语 7.3 理解类 7.3.1 定义类 7.3.2 声明类的对象 7.3.3 访问类的数据成员 7.3.4 类的成员函数 7.3.5 成员函数定义的位置 7.3.6 内联函数 7.4 类构造函数 7.4.1 构造函数的概念 7.4.2 默认的构造函数 7 4.3 在类定义中指定默认的形参值 7.4.4 在构造函数中使用初始化列表 7.5 类的私有成员 7.5.1 访问私有类成员 7.5.2 类的友元函数 7.5.3 默认复制构造函数 7.6 this指针 7.7 类的const对象 7.7.1 类的const成员函数 7.7.2 类外部的成员函数定义 7.8 类对象的数组 7.9 类的静态成员 7.9.1 类的静态数据成员 7.9.2 类的静态函数成员 7.10 类对象的指针和引用 7.10.1 类对象的指针 7.10.2 类对象的引用 7.11 C++/CLI编程 7.11.1 定义数值类类型 7.11.2 定义引用类类型 7.11.3 类属性 7.11.4 initonly字段 7.11.5 静态构造函数 7.12 小结 7.13 练习 第8章 深入理解类 8.1 类的析构函数 8.1.1 析构函数的概念 8.1.2 默认的析构函数 8.1.3 析构函数与动态内存分配 8.2 实现复制构造函数 8.3 在变量之间共享内存 8.3.1 定义联台 8.3.2 匿名联合 8.3.3 类和结构中的联合 8.4 运算符重载 8.4.1 实现重载的运算符 8.4.2 实现对运算符的完全支持 8.4.3 重载赋值运算符 8.4.4 重载加法运算符 8.4.5 重载递增和递减运算符 8.5 类模板 8.5.1 定义类模板 8.5.2 根据类模板创建对象 8.5.3 使用有多个形参的类模板 8.6 使用类 8.6.1 类接口的概念 8.6.2 定义问题 8.6.3 实现CBox类 8.6.4 定义CBox类 8.6.5 使用CBox类 8.7 组织程序代码 8.8 C++/CLI编程 8.8.1 在数值类中重载运算符 8.8.2 重载递增和递减运算符 8.8.3 在引用类中重载运算符 8.9 小结 8.1O 练习 第9章 类继承和虚函数 9.1 面向对象编程的基本思想 9.2 类的继承 9.2.1 基类的概念 9.2.2 基类的派生类 9.3 继承机制下的访问控制 9.3.1 派生类中构造函数的操作 9.3.2 声明类的保护成员 9.3.3 继承类成员的访问级别 9.4 派生类中的复制构造函数 9.5 友元类成员 9.5.1 友元类 9.5.2 对类友元关系的限制 9.6 虚函数 9.6.1 虚函数的概念 9.6.2 使用指向类对象的指针 9.6.3 使用引用处理虚函数 9.6.4 纯虚函数 9.6.5 抽象类 9.6.6 间接基类 9.6.7 虚析构函数 9.7 类类型之间的强制转换 9.8 嵌套类 9.9 C++/CLI编程 9.9.1 C++/CLI类的继承 9.9.2 接口类 9.9.3 定义接口类 9.9.4 类和程序集 9.9.5 被指定为new的函数 9.9.6 委托和事件 9.9.7 引用类的析构函数和结束函数 9.9.8 通用类 9.10 小结 9.11 练习 第10章 调试技术 10.1 理解调试 10.1.1 程序故障 10.1.2 常见故障 10.2 基本的调试操作 10.2.1 设置断点 10.2.2 设置跟踪点 10.2.3 启动调试模式 10.2.4 修改变量的值 10.3 添加调试代码 10.3.1 使用断言 10.3.2 添加自己的调试代码 10.4 调试程序 10.4.1 调用堆栈 10.4.2 单步执行到出错位置 10.5 测试扩展的类 10.6 调试动态内存 10.6.1 检查自由存储器的函数 10.6.2 控制自由存储器的调试操作 10.6.3 自由存储器的调试输出 10.7 调试C++/CLI程序 10.8 小结 第11章 Windows编程的概念 11.1 Windows编程基础 11.1.1窗口的元素 11.1.2 Windows程序与操作系统 11.1.3事件驱动型程序 11.1.4 Windows消息 11.1.5 WindowsAPI 11.1.6.Windows数据类型 11.1.7 Windows程序中的符号 11.2 Windows程序的结构 11.2.1 WinMain()函数 11.2.2消息处理函数 11.2.3简单的Windows程序 11.3 Windows程序的组织 11.4 MFC 11.4.1 MFC标记法 11.4.2 MFC程序的组织方式 11.5使用Windows Forms 11.6小结 第12章 使用MFC编写Windows程序 12.1 MFC的文档,视图概念 12.1.1 文档的概念 12.1.2 文档界面 12.1.3 视图的概念 12.1.4 连接文档和视图 12.1.5 应用程序和MFC 12.2 创建MFC应用程序 12.2.1 创建SDI应用程序 12.2.2 MFCApplicationwizard的输出 12.2.3 创建MDI应用程序 12.3 小结 12.4 练习 第13章 处理菜单和工具栏 13.1 与Windows进行通信 13.1.1 了解消息映射 13.1.2 消息类别 13.1.3 处理程序中的消息 13.2 扩充Sketcher程序 13.3 菜单的元素 13.4 为菜单消息添加处理程序 13.4.1 选择处理菜单消息的类 13.4.2 创建菜单消息函数 13.4.3 编写菜单消息函数的代码 13.4.4 添加更新用户界面的消息处理程序 13.5 添加工具栏按钮 13.5.1 编辑工具栏按钮的属性 13.5.2 练习使用工具栏按钮 13.5.3 添加工具提示 13.6 小结 13.7 练习题 第14章 在窗口中绘图 14.1 窗口绘图的基础知识 14.1.1 窗口客户区 14.1.2 Windows图形设备界面 14.2 Visual C++中的绘图机制 14.2.1 应用程序中的视图类 14.2.2 CDC类 14.3 实际绘制图形 14.4 对鼠标进行编程 14.4.1 鼠标发出的消息 14.4.2 鼠标消息处理程序 14.4.3 使用鼠标绘图 14.5 练习使用Sketcher程序 14.5.1 运行这个示例 14.5.2 捕获鼠标消息 14.6 小结 14.7 练习题 第15章 创建文档和改进视图 15.1 什么是集合类 15.1.1 集合的类型 15.1.2 类型安全的集合类 15.1.3 对象集合 15.1.4 类型化指针集合 15.2 使用CList模板类 15.2.1 绘制曲线 15.2.2 定义CCurve类 15.2.3 实现CCurve类 15.2.4 练习使用CCurve类 15.3 创建文档 15.4 改进视图 15.4.1 更新多个视图 15.4.2 滚动视图 15.4.3 使用MM_LOENGLISH映射模式 15.5 删除和移动形状 15.6 实现上下文菜单 15.6.1 关联菜单和类 15.6.2 选择上下文菜单 15.6.3 醒目显示元素 15.6.4 处理菜单消息 15.7 处理被屏蔽的元素 15.8 小结 15.9 练习 第16章 使用对话框和控件 16.1 理解对话框 16.2 理解控件 16.3 创建对话框资源 16.4 对话框的编程 16.4.1 添加对话框类 16.4.2 模态和非模态对话框 16.4.3 显示对话框 16.5 支持对话框控件 16.5.1 初始化控件 16.5.2 处理单选按钮消息 16.6 完成对话框的操作 16.6.1 给文档类添加存储线宽的成员 16.6.2 给元素添加线宽 16.6.3 在视图中创建元素 16.6.4 练习使用对话框 16.7 使用微调按钮控件 16.7.1 添加Scale菜单项和工具栏按钮 16.7.2 创建微调按钮 16.7.3 生成比例对话框类 16.7.4 显示微调按钮 16.8 使用比例系数 16.8.1 可缩放的映射模式 16.8.2 设置文档的大小 16.8.3 设置映射模式 16.8.4 同时实现滚动与缩放 16.9 使用状态栏 16.10 使用列表框 16.10.1 删除比例对话框 16.1O.2 创建列表框控件 16.11 使用编辑框控件 16.11.1 创建编辑框资源 16.11.2 创建对话框类 16.11.3 添加Text菜单项 16.11.4 定义文本元素 16.11.5 实现CText类 16.11.6 创建文本元素 16.12 小结 16.13 练习 第17章 存储和打印文档 17.1 了解串行化 17.2 串行化文档 17.2.1 文档类定义中的串行化 17.2.2 丈档类实现中的串行化 17.2.3 基于CObject的类的功能 17.2.4 串行化的工作方式 17.2.5 如何实现类的串行化 17.3 应用串行化 17.3.1 记录文档修改 17.3.2 串行化文档 17.3.3 串行化元素类 17.4 练习串行化 17.5 移动文本 17.6 打印文档 17.7 实现多页打印 17.7.1 获取文档的总尺寸 17.7.2 存储打印数据 17.7.3 准备打印 17.7.4 打印后的清除 17.7.5 准备设备上下文 17.7.6 打印文档 17.7.7 获得文档的打印输出 17.8 小结 17.9 练习题 第18章 编写自己的DLL 18.1 了解DLL 18.1.1 DLL的工作方式 18.1.2 DLL的内容 18.1.3 DLL变体 18.2 决定放入DLL的内容 18.3 编写DLL 18.3.1 编写和使用扩展DLL 18.3.2 从DLL中导出变量和函数 18.3.3 将符号导入程序 18.3.4 实现符号从DLL的导出 18.4 小结 18.5 练习题 第19章 连接到数据源 19.1 数据库基础知识 19.2 SQL 19.2.1 使用SQL检索数据 19.2.2 使用SQL连接表 19.2.3 对记录进行排序 19.3 MFC中的数据库支持 19.4 创建数据库应用程序 19.4.1 注册ODBC数据库 19.4.2 生成MFC ODBC程序 19.4.3 了解程序结构 19.4.4 示例练习 19.5 对记录集进行排序 19.6 使用另一个记录集对象 19.6.1 添加记录集类 19.6.2 添加记录集的视图类 19.6.3 定制记录集 19.6.4 访问多个表视图 19.6.5 查看产品的订单 19.7 查看客户的详细情况 19.7.1 添加客户记录集 19.7.2 创建客户对话框资源 19.7.3 创建客户视图类 19.7.4 添加过滤器 19.7.5 实现过滤器参数 19.7.6 链接订单对话框和客户对话框 19.7.7 练习使用数据库查看器 19.8 小结 19.9 练习题 第20章 更新数据源 20.1 更新操作 20.1.1 CRecordset更新操作 20.1.2 事务 20.2 简单的更新示例 20.3 管理更新过程 20.4 向表中添加行 20.4.1 订单录入过程 20.4.2 创建资源 20.4.3 创建记录集 20.4.4 创建记录集视图 20.4.5 给对话框资源添加控件 20.4.6 实现对话框切换 20.4.7 创建订单ID 20.4.8 存储订单数据 20.4.9 为订单选择产品 20.4.10 添加新订单 20.5 小结 20.6 练习 第21章 使用Windows Forms的应用程序 21.1 理解Wqndows Forms 21.2 理解Windows Forms应用程序 21.2.1 修改窗体的属性 21.2.2 如何启动应用程序 21.3 定制应用程序GUI 21.3.1 给窗体添加控件 21.3.2 添加选项卡控件 21.3.3 使用CroupBox控件 21.3.4 使用Button控件 21.3.5 使用WebBrowser控件 21.3.6 Winning应用程序的操作 21.3.7 添加上下文菜单 21.3.8 创建事件处理程序 21.3.9 处理Limits菜单的事件 21.3.10 创建对话框 21.3.11 使用对话框 21.3.12 添加第二个对话框 21.3.13 实现Help|About菜单项 21.3.14 处理按钮单击事件 21.3.15 响应上下文莱单 21.4 小结 21.5 练习 第22章 在Windows Forms应用程序中访问数据源 22.1 使用数据源 22.2 访问并显示数据 22.3 使用DataGridView控件 22.4 在无约束模式中使用DataGridView控件 22.5 定制DataGridView控件 22.5.1 定制题头单元格 22.5.2 定制非题头单元格 22.5.3 动态设置单元格样式 22.6 使用约束模式 22.7 BindingSource组件 22.8 使用BindingNavigator控件 22.9 绑定到单独的控件 22.10 使用多个表 22.11 小结 22.12 练习 附录A C++关键字 A1 ISO/ANSI C++关键宇 A2 C++/CLI关键字 附录B ASCII码

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值