MFC学习随笔(2)
在MFC中,有时需要多个类之间传递信息,一个共通的头文件是个不错的选择。如果在头文件中直接声明一个变量的话,势必会报出一个错误:
error LNK2005: "struct my_global global_data" (?global_data@@3Umy_global@@A) already defined in MFCApplication1Dlg.obj
不对呀,我明明是在头文件声明的,不同的文件中的变量应该是同一个啊,怎么还重定义了呢?
反复查证之后,原来是自己对头文件的理解一直有错误。
引用一篇好文:http://www.oschina.net/question/253403_44866?sort=time
摘要部分如下:
“楼主的问题,是对头文件作用不太了解造成了。头文件本质只是个文本。连源文件都算不上。有些编译器会对.h文件做写特殊化的处理。
但是希望你理解,.h头 文件自身没有意义,有意义的是#include ,你参考我下面的一个代码例子,不知道你是否能理解,我用C写的,
C++也基本一样,在使用 #include方面。”
//这是一个很简单的程序,就一个main.c函数
#include <stdio.h>
int main(int argc ,char *argv[]){
printf("hello world!\n");
return ;
}
//我把上面修改一下,新生成两个文本文件,printf_hello_world.txt ,return.txt
//printf_hello_world.txt里面的内容就一行
printf("hello world!\n"); //return.txt里面的内容也就一行
return ; //同时修改main.c文件如下
#include <stdio.h>
int main(int argc ,char *argv[]){
#include "printf_hello.world.txt"
#include "return.txt"
}
"你可以发现,修改后的代码和原始代码运行是一个结果。准确说,对编译器而言,是完全一样的内容。
#include只是将后面的文件,插入到当前的文本中。其实和.h无关。
而你将一个函数写在.h里面当多个文件均#include时,则这个函数对于多个文件,再编译器看来,每个文件都存在完全相同的函数
(只要函数定义 相同就会有冲突)。而C语言或C++,默认对每个函数是可作为外部函数的。此时,连接器就会混乱。究竟连接哪
个文本(源文件)所编译对应的函数。
你可以把函数写在头文件里,但需要增加static 前缀。此时这个函数就会在每个#include该头文件的源文件中存在,由于是static,
对于函数是局部的意思,此时,外部就无法 调用到该函数,最多会出现”找不到该函数的连接错误“而不会说函数重复存在的问题。"
自然,如果我在头文件中声明变量直接引用的话,就会造成变量重定义的错误。那么该如何正确使用头文件呢?对于函数,我们使用static,对于变量,我们则使用extern。
具体方法如下:
在头文件中,添加extern变量:
extern my_global global_data;
在主对话框中,再次声明该变量:
my_global global_data;
那么在所有文件中,只要引入头文件,就可以调用该变量了。
extern的使用是一个基础知识,搞得我昏头昏脑,很是惭愧= = 头文件的正确打开方式则是个意外收获,曰:nice。
MFC学习随笔(2)的更多相关文章
- MFC学习随笔(1)
最近在学习用MFC编写一个简单的界面.其实MFC并不是十分复杂的,经过一段时间的熟悉就可以实现许多基础功能.但是在编写的过程中,经常会遇到林林总总的bug,让人摸不到头脑.今天记录一个过去没有注意过的 ...
- MFC 学习之 鼠标移动到Toolbar按钮上显示提示信息(tooltip),状态栏也随之改变
1.在ResourceView里加入Toolbar资源,命名IDR_TOOLBAR1 2.在主程序的.h文件中加入变量: CToolBar m_toolbar;CImageList ...
- (转) 基于Theano的深度学习(Deep Learning)框架Keras学习随笔-01-FAQ
特别棒的一篇文章,仍不住转一下,留着以后需要时阅读 基于Theano的深度学习(Deep Learning)框架Keras学习随笔-01-FAQ
- C#程序集Assembly学习随笔(第一版)_AX
①什么是程序集?可以把程序集简单理解为你的.NET项目在编译后生成的*.exe或*.dll文件.嗯,这个确实简单了些,但我是这么理解的.详细:http://blog.csdn.net/sws8327/ ...
- Hive入门学习随笔(一)
Hive入门学习随笔(一) ===什么是Hive? 它可以来保存我们的数据,Hive的数据仓库与传统意义上的数据仓库还有区别. Hive跟传统方式是不一样的,Hive是建立在Hadoop HDFS基础 ...
- JavaScript ES6 数组新方法 学习随笔
JavaScript ES6 数组新方法 学习随笔 新建数组 var arr = [1, 2, 2, 3, 4] includes 方法 includes 查找数组有无该参数 有返回true var ...
- 64位BASM学习随笔(一)
64位BASM学习随笔(一) Delphi的BASM一直是我最喜爱的内嵌汇编语言,同C/C++的内联汇编相比,它更方便,更具灵活性,由于C/C++的内联汇编仅仅能是或插入式的汇编代码,函数花括号 ...
- typeScript学习随笔(一)
TypeScript学习随笔(一) 这么久了还不没好好学习哈这么火的ts,边学边练边记吧! 啥子是TypeScript TypeScript 是 JavaScript 的一个超集,支持 es6 标准 ...
- MFC学习笔记1---准备工作
什么是MFC MFC,全称Microsoft Foundation Classes,微软基础类库,顾名思义,是微软的攻城狮们将一些常用的基础的Windows API 函数用C++的形式封装成类,简化程 ...
随机推荐
- oracle计算时间秒数差
--计算plsql处理时间差 --qzq declare time1 timestamp; --开始时间 time2 timestamp; --结束时间 sum1 ); --时间差(s) begin ...
- Python模块:hashlib
hashlib:提供了常见的摘要算法,如MD5,SHA1等. import hashlib m = hashlib.md5() m.update('how to use md5 in python h ...
- C#图片压缩处理算法
原文链接:http://blog.csdn.net/szstephenzhou/article/details/38900345
- Surface、SurfaceView、SurfaceHolder及SurfaceHolder.Callback之间的关系
转载请包含网址:http://blog.csdn.net/pathuang68/article/details/7351317 一.Surface Surface就是“表面”的意思.在SDK的文档中, ...
- windows环境下安装vue+webpack的开发环境
本人最近在学习vue,在学习的过程中遇到对的问题和解决方法 1.我们首先要安装node.js.node.js的官方地址为:https://nodejs.org/en/download/,下载完毕,按照 ...
- MMS源码中异步处理简析
1,信息数据的查询,删除使用AsycnQueryHandler处理 AsycnQueryHandler继承了Handler public abstract class AsyncQueryHandle ...
- 如何辨别具体的一种SaaS是否安全?
如何辨别具体的一种SaaS是否安全,需要把握以下几点: 1.传输协议加密 首先,要看SaaS产品提供使用的协议,是https://还是一般的http://,别小看这个s,这表明所有的数据在传输过程中都 ...
- 在ubuntu14.04上部署基于Docker的Gitlab
首先在一台新的ubuntu上执行更新: sudo apt-get update 然后安装docker(采用国内源) curl -sSL https://get.daocloud.io/docker | ...
- Android学习 之 ColorStateList按钮文字变色
首先添加一个ColorStateList资源XML文件,XML文件保存在res/color/button_text.xml: <?xml version="1.0" enco ...
- STM32 GPIO外部中断总结
一.STM32中断分组: STM32 的每一个GPIO都能配置成一个外部中断触发源,这点也是 STM32 的强大之处.STM32 通过根据引脚的序号不同将众多中断触发源分成不同的组,比如:PA0,PB ...