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++工程中设置全局函数

我刚学C语言 怎么样让一个变量到其他的文件也能用?

在C++工程中main函数之前跑代码的廉价方法(使用全局变量和全局函数)

C语言中怎样在头文件中定义一个能够在所有文件中都可以使用的全局数组变量 ?

C++入门学习

c语言工程里其它文件引用全局变量?