C++ 怎么定义一个全局函数,能够在一个工程的所有文件中使用!
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++ 怎么定义一个全局函数,能够在一个工程的所有文件中使用!相关的知识,希望对你有一定的参考价值。
问题描述:在头文件log.h中定义了一个LOG函数(就一个普通函数,不是类成员函数),用于向文件中写日志,然后在其他类中把log.h头文件包含进来。编译链接是时会出现 :“ error LNK2005: "void __cdecl log(char *)" (?log@@YAXPAD@Z) 已经在 Adapter.obj 中定义”这样的错误提示
这应该是你的log.h文件写的有问题。由于log.h应该是一个各个模块都要使用的模块,所以其他cpp文件或者h文件均会include这个log.h文件,这就会导致编译器多次解析log.h文件中的函数,所以会出现重定义。解决方法是,在log.h头文件的最开始加上:
#ifndef __LOG_H__
#define __LOG_H__
//log.h头文件的全部代码
#endif // __LOG_H__
这样log.h头文件无论被引用多少次都只会被解析一次.
另外要说的这不是纯c++编程,这种用法属于c与c++的混合编程。还有一个需要注意的点,在编译器编译函数的时候为了实现函数的重载和同名函数,编译器会将函数的名字进行修改。这又涉及到调用约定的问题,不同的调用约定的模块之间没法调用函数。向你上面的报错信息中的__cdecl就是vs的默认调用约定。关于调用约定与语言的多种组合的问题,你可以上网去搜索一下,在vs上编程时一定要注意。 参考技术A 在log.h中只写函数的声明,另外建立一个log.cpp的文件,把函数的实现都移到这个cpp文件中去就可以了。
其他方法如下:
1:在头文件是声明变量,然后在使用的文件中用exten标识。
".h":
int ntemp;
".cpp":
exten int ntemp;
2:定义一个全局变量类,使用时包含头文件即可:
"GlobalVar.h"
Class CGlobalVar
CGlobalVr();
~CGlobal();
static int ntemp; //用static
;
"GlobalVar.cpp"
int CGlobalVar::ntemp = 0;//定义并初始化
CGlobalVar::CGlobalVar()
CGlobalVar::~CGlobalVar()
3:全局函数可以用上面2的做法外还可以:
在".h"里声明
int GetDataTime(CString strDataTime, CString strSep);
在".cpp"里实现
int GetDataTime(CString strDataTime, CString strSep)
....
使用时只是将".h"文件包含进去即可。 参考技术B 在log.h中只写函数的声明
另外建立一个log.cpp的文件,把函数的实现都移到这个cpp文件中去就可以了。
全局函数就是可以被其他文件中函数调用,比如一个大型程序,由很多人来共同编写,每个人写的程序为一个文件,全局函数就可以被另一个文件中的程序调用,声明函数时不管写没写extern都默认为全局函数,如果不想被其他人调用,可以用static来定义,就只能被本文件程序调用
全局函数是定义在类外的函数,成员函数就是定义在类中的函数。 参考技术C 在log.h中只写函数的声明
另外建立一个log.cpp的文件,把函数的实现都移到这个cpp文件中去就可以了 参考技术D 典型的重复定义问题
解决方法1:新建一个log.cpp,把log.h中LOG函数的定义挪过去,其他文件只需包含log.h头文件就行。
解决方法2:不用修改,去掉其他文件中的log.h头文件,把函数LOG声明一下;(推荐)
java与C++的区别
1、所有东西都必须置入一个类。不存在全局函数或者全局数据。如果想获得与全局函数等价的功能,可考虑将static方法和static数据置入一个类里。注意没有象结构、枚举或者联合这一类的东西,一切只有“类”(Class)!
2、 在Java中,类定义采取几乎和C++一样的形式。但没有标志结束的分号。没有class foo这种形式的类声明,只有类定义。
3、Java中没有作用域范围运算符“::”。Java利用点号做所有的事情,但可以不用考虑它,因为只能在一个类里定义元素。即使那些方法定义,也必须在一个类的内部,所以根本没有必要指定作用域的范围。我们注意到的一项差异是对static方法的调用:使用ClassName.methodName()。除此以外,package(包)的名字是用点号建立的,并能用import关键字实现C++的“#include”的一部分功能。
4、 静态引用的字串会自动转换成String对象。和C及C++不同,没有独立的静态字符数组字串可供使用。
5、java数组名是对象,数组保存的仅仅是对象的引用,而不是对象本身,而c++数组名是数据结构。JAVA里数组的内存分配是在堆里面的,必须用new来分配,而C++里面是在栈里面分配的,定义的时候会自动分配。
6、Java中不必进行提前声明。若想在定义前使用一个类或方法,只需直接使用它即可——编译器会保证使用恰当的定义。所以和在C++中不同,我们不会碰到任何涉及提前引用的问题。
7、 被定义成类成员的对象句柄会自动初始化成null。对基本类数据成员的初始化在Java里得到了可靠的保障。若不明确地进行初始化,它们就会得到一个默认值(零或等价的值)。可对它们进行明确的初始化(显式初始化):要么在类内定义它们,要么在构建器中定义。采用的语法比C++的语法更容易理解,而且对于static和非static成员来说都是固定不变的。我们不必从外部定义static成员的存储方式,这和C++是不同的
8、在Java里,没有象C和C++那样的指针。用new创建一个对象的时候,会获得一个引用(本书一直将其称作“句柄”)。例如:
String s = new String("howdy");
然而,C++引用在创建时必须进行初始化,而且不可重定义到一个不同的位置。但Java引用并不一定局限于创建时的位置。它们可根据情况任意定义,这便消除了对指针的部分需求。在C和C++里大量采用指针的另一个原因是为了能指向任意一个内存位置(这同时会使它们变得不安全,也是Java不提供这一支持的原因)。
9、Java中没有“破坏器”(Destructor)。变量不存在“作用域”的问题。一个对象的“存在时间”是由对象的存在时间决定的,并非由垃圾收集器决定。有个finalize()方法是每一个类的成员,它在某种程度上类似于C++的“破坏器”。但finalize()是由垃圾收集器调用的,而且只负责释放“资源”(如打开的文件、套接字、端口、URL等等)。由于Java不支持破坏器的概念,所以在必要的时候,必须谨慎地创建一个清除方法
10、 Java中没有goto。它采取的无条件跳转机制是“break 标签”或者“continue 标准”,用于跳出当前的多重嵌套循环。
11、Java采用了一种单根式的分级结构,因此所有对象都是从根类Object统一继承的。而在C++中,我们可在任何地方启动一个新的继承树,所以最后往往看到包含了大量树的“一片森林”。在Java中,我们无论如何都只有一个分级结构。尽管这表面上看似乎造成了限制,但由于我们知道每个对象肯定至少有一个Object接口,所以往往能获得更强大的能力。C++目前似乎是唯一没有强制单根结构的唯一一种OO语言。
12、“垃圾收集”意味着在Java中出现内存漏洞的情况会少得多,但也并非完全不可能(若调用一个用于分配存储空间的固有方法,垃圾收集器就不能对其进行跟踪监视)。
13、Java内建了对多线程的支持。利用一个特殊的Thread类,我们可通过继承创建一个新线程(放弃了run()方法)。若将synchronized(同步)关键字作为方法的一个类型限制符使用,相互排斥现象会在对象这一级发生。在任何给定的时间,只有一个线程能使用一个对象的synchronized方法。在另一方面,一个synchronized方法进入以后,它首先会“锁定”对象,防止其他任何synchronized方法再使用那个对象。只有退出了这个方法,才会将对象“解锁”。在线程之间,我们仍然要负责实现更复杂的同步机制,方法是创建自己的“监视器”类。递归的synchronized方法可以正常运作。若线程的优先等级相同,则时间的“分片”不能得到保证。
14、Java中的继承具有与C++相同的效果,但采用的语法不同。Java用extends关键字标志从一个基础类的继承,并用super关键字指出准备在基础类中调用的方法,它与我们当前所在的方法具有相同的名字(然而,Java中的super关键字只允许我们访问父类的方法——亦即分级结构的上一级)。通过在C++中设定基础类的作用域,我们可访问位于分级结构较深处的方法。亦可用super关键字调用基础类构建器。正如早先指出的那样,所有类最终都会从Object里自动继承。和C++不同,不存在明确的构建器初始化列表。但编译器会强迫我们在构建器主体的开头进行全部的基础类初始化,而且不允许我们在主体的后面部分进行这一工作。
15、 Java中没有virtual关键字,因为所有非static方法都肯定会用到动态绑定。在Java中,程序员不必自行决定是否使用
16、Java语言不需要程序对内存进行分配和回收。Java丢弃了C++ 中很少使用的、很难理解的、令人迷惑的那些特性,如操作符重载、多继承、自动的强制类型转换。特别地,Java语言不使用指针,并提供了自动的废料收 集,Examda提示: 在Java语言中,内存的分配和回收都是自动进行的,程序员无须考虑内存碎片的问题。
17、Java用接口(Interface)技术取代C++程序中的多继承性。接口与多继承有同样的功能,但是省却了多继承在实现和维护上的复杂性。
18、多重继承 c++支持多重继承,这是c++的一个特征,它允许多父类派生一个类。尽管多重继承功能很强,但使用复杂,而且会引起许多麻烦,编译程序实现它也很不容易。Java不支持多重继承,但允许一个类继承多个接口(extends+implement),实现了c++多重继承的功能,又避免了c++中的多重继承实现方式带来的诸多不便。
19、预处理功能 Java不支持预处理功能。c/c++在编译过程中都有一个预编泽阶段,即众所周知的预处理器。预处理器为开发人员提供了方便,但增加了编译的复杂性。JAVA虚拟机没有预处理器,但它提供的引入语句(import)与c++预处理器的功能类似。
20、Java不支持缺省函数参数,而c++支持
21、字符串 c和c++不支持字符串变量,在c和c++程序中使用Null终止符代表字符串的结束,在Java中字符串是用类对象(strinR和stringBuffer)来实现的,这些类对象是Java语言的核心
22、
异常 JAVA中的异常机制用于捕获例外事件,增强系统容错能力
1
2
3
4
5
6
7
|
try//可能产生例外的代码 catch(exceptionType name) //处理
|
其中exceptionType表示异常类型。而C++则没有如此方便的机制。
以上是关于C++ 怎么定义一个全局函数,能够在一个工程的所有文件中使用!的主要内容,如果未能解决你的问题,请参考以下文章
在C++工程中main函数之前跑代码的廉价方法(使用全局变量和全局函数)