宏的使用,链接出错,请教!

asksgp 2009-08-17 04:09:44
写了个宏,主要想实现打印文件名,文件行号功能;但在一个cpp文件调用时没问题,多个cpp文件该宏时就链接出错。
宏定义:
t.h

#ifndef BaseLog_H
#define BaseLog_H

#include<cstdio>
#include<string>
#include<process.h>
#include<stdarg.h>
using namespace std;

#define DEBUG printf("[File:%s,Line:%d,Fun:%s] \n",__FILE__,__LINE__,__FUNCTION__)
//#define TRACE printf
#define LOG SetLine(__LINE__),SetFile(__FILE__),log
char *mfilename;
int mline;
void SetLine(int num)
{
mline=num;
};
void SetFile(char *filenm)
{
mfilename=filenm;
};
void log(const char* traceMessage, ...)
{
char chSendbuf[1025] = {0};
memset(chSendbuf, 0, 1024);

va_list ap;
va_start(ap, traceMessage);
vsprintf(chSendbuf, traceMessage, ap);
va_end(ap);

string Sendbuf;
int iBufLen = strlen(chSendbuf);
while ( iBufLen > 0 )
{
if ( chSendbuf[iBufLen-1]== '\n' || chSendbuf[iBufLen-1] == '\r' )
{
--iBufLen ;
continue ;
}
else
{
Sendbuf = chSendbuf+iBufLen ;
chSendbuf[iBufLen] = 0 ;
break ;
}
}
if ( Sendbuf.length() == 0 ) Sendbuf = "\n" ;

char tmp[2048] = {0};
if(mline > 1)
{
// Date nowtime = Date::GetCurrentTime();
// nowtime.toString();
// sprintf(tmp,"![%s](%d)[%d]%s %s%s",nowtime.toString().c_str(),GetFilelineNum(),getpid(),chSendbuf,Sendbuf.c_str());
sprintf(tmp,"(%d)[%s][Line:%d]%s %s",getpid(),mfilename,mline,chSendbuf,Sendbuf.c_str());
}
else if( mline == 1)
sprintf(tmp, "(%d)[%s][Line:%d]%s%s",getpid(),mfilename,mline,chSendbuf,Sendbuf.c_str());
else
sprintf(tmp, "(%d)[%s][Line:%d]%s%s",getpid(),mfilename,mline,chSendbuf,Sendbuf.c_str());

printf("%s\n",tmp);
};

#endif


宏使用1
tt.cpp

#include"tt.h"
#include"add.h"

int main(int argc,char *argv[])
{
long a=10000;
LOG("%d",argc);
for(int i=0;i<argc;i++)
{
LOG("%s,%ld",argv[i],a);
}
LOG("end");

int x=100,y=200;
CAdd myadd;
myadd.add(x,y);

return 0;
}


宏使用2
add.h


#ifndef Add_H
#define Add_H

#include"tt.h"

class CAdd
{
public:
CAdd() ;
virtual ~CAdd() ;
static int add(int a,int b);
};
#endif

add.cpp


#include"add.h"

CAdd::CAdd()
{
}
CAdd::~CAdd()
{
}

int CAdd::add(int a,int b)
{
LOG("%d,%d,sum=%d",a,b,a+b);
return a+b;
}


出错:
Linking...
tt.obj : error LNK2005: "char * mfilename" (?mfilename@@3PADA) already defined in add.obj
tt.obj : error LNK2005: "int mline" (?mline@@3HA) already defined in add.obj
tt.obj : error LNK2005: "void __cdecl SetLine(int)" (?SetLine@@YAXH@Z) already defined in add.obj
tt.obj : error LNK2005: "void __cdecl SetFile(char *)" (?SetFile@@YAXPAD@Z) already defined in add.obj
tt.obj : error LNK2005: "void __cdecl log(char const *,...)" (?log@@YAXPBDZZ) already defined in add.obj
F:\learn\code\090806\Debug\090806.exe : fatal error LNK1169: one or more multiply defined symbols found
Build log was saved at "file://f:\learn\code\090806\090806\Debug\BuildLog.htm"

麻烦高手帮忙看看,多谢!
...全文
350 41 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
41 条回复
切换为时间正序
请发表友善的回复…
发表回复
kingstarer 2009-10-13
  • 打赏
  • 举报
回复
#define LOG printf("(%d)[%s]", __LINE__, __FILE__), log

这样不知道行不行
rendao0563 2009-08-18
  • 打赏
  • 举报
回复
不需要。
直接用就好了。
一般情况FILE FUNCTION只需要用一个。
taodm 2009-08-18
  • 打赏
  • 举报
回复
#define LOG(x) log(__FILE__, __LINE__, x)
使用
LOG((。。。。));
asksgp 2009-08-18
  • 打赏
  • 举报
回复
非常感谢晨雨,你是如何实现类似功能的?有无比这个更简单的方法?
还有taodm说不需要那两个全局变量,我觉得必须有啊?
asksgp 2009-08-18
  • 打赏
  • 举报
回复
有人说不需要2个全局变量;
#define LOG(x) log(__FILE__, __LINE__, x)
使用
LOG((。。。。));
就是不用这个2个变量,这个宏该如何写呢?
[Quote=引用 38 楼 zgjxwl 的回复:]
什么问题?要源代码的话。。。网上很多啊。。

http://sourceforge.net/

http://csourcesearch.net/

http://www.cplusplus.com/src/

http://www.codeproject.com/
[/Quote]
fallening 2009-08-18
  • 打赏
  • 举报
回复
#ifndef BaseLog_H
#define BaseLog_H

#include<cstdio>
#include<string>
#include<process.h>
#include<stdarg.h>
using namespace std;

#define DEBUG printf("[File:%s,Line:%d,Fun:%s] \n",__FILE__,__LINE__,__FUNCTION__)
#define LOG SetLine(__LINE__),SetFile(__FILE__),log
char *mfilename;
int mline;
inline void SetLine(int num)
{
mline=num;
};
inline void SetFile(char *filenm)
{
mfilename=filenm;
};
inline void log(const char* traceMessage, ...)
{
char chSendbuf[1025] = {0};
memset(chSendbuf, 0, 1024);

va_list ap;
va_start(ap, traceMessage);
vsprintf(chSendbuf, traceMessage, ap);
va_end(ap);

string Sendbuf;
int iBufLen = strlen(chSendbuf);
while ( iBufLen > 0 )
{
if ( chSendbuf[iBufLen-1]== '\n' || chSendbuf[iBufLen-1] == '\r' )
{
--iBufLen ;
continue ;
}
else
{
Sendbuf = chSendbuf+iBufLen ;
chSendbuf[iBufLen] = 0 ;
break ;
}
}
if ( Sendbuf.length() == 0 ) Sendbuf = "\n" ;

char tmp[2048] = {0};
if(mline > 1)
{
// Date nowtime = Date::GetCurrentTime();
// nowtime.toString();
// sprintf(tmp,"![%s](%d)[%d]%s %s%s",nowtime.toString().c_str(),GetFilelineNum(),getpid(),chSendbuf,Sendbuf.c_str());
sprintf(tmp,"(%d)[%s][Line:%d]%s %s",getpid(),mfilename,mline,chSendbuf,Sendbuf.c_str());
}
else if( mline == 1)
sprintf(tmp, "(%d)[%s][Line:%d]%s%s",getpid(),mfilename,mline,chSendbuf,Sendbuf.c_str());
else
sprintf(tmp, "(%d)[%s][Line:%d]%s%s",getpid(),mfilename,mline,chSendbuf,Sendbuf.c_str());

printf("%s\n",tmp);
};

#endif

zgjxwl 2009-08-18
  • 打赏
  • 举报
回复
什么问题?要源代码的话。。。网上很多啊。。

http://sourceforge.net/

http://csourcesearch.net/

http://www.cplusplus.com/src/

http://www.codeproject.com/
asksgp 2009-08-18
  • 打赏
  • 举报
回复
up 解答完这个问题就给分。。。
asksgp 2009-08-18
  • 打赏
  • 举报
回复
能否给下代码学习学习,搞了半天不知道怎么写。。。[Quote=引用 34 楼 rendao0563 的回复:]
不需要。
直接用就好了。
一般情况FILE FUNCTION只需要用一个。

[/Quote]
zgjxwl 2009-08-18
  • 打赏
  • 举报
回复
[Quote=引用 32 楼 asksgp 的回复:]
非常感谢晨雨,你是如何实现类似功能的?有无比这个更简单的方法?
还有taodm说不需要那两个全局变量,我觉得必须有啊?
[/Quote]
一般不要把定义,也就是实现放到头文件里。。。头文件里一般放声明
我只是外部声明了下。。表示它的定义在其他cpp里
zgjxwl 2009-08-17
  • 打赏
  • 举报
回复
add.cpp忘记把注释语句放出来了。。。。

重贴一下。。


//add.cpp

#include"add.h"

CAdd::CAdd()
{
}
CAdd::~CAdd()
{
}

int CAdd::add(int a,int b)
{
LOG("%d,%d,sum=%d",a,b,a+b);
return a+b;
}



这里的运行结果:

(3512)[f:\ct8\csdn\tt.cpp][Line:9]1

(3512)[f:\ct8\csdn\tt.cpp][Line:12]F:\CT8\ads\Debug\ads.exe,10000

(3512)[f:\ct8\csdn\tt.cpp][Line:14]end

(3512)[f:\ct8\csdn\add.cpp][Line:14]100,200,sum=300

Press any key to continue


zgjxwl 2009-08-17
  • 打赏
  • 举报
回复
//tt.h

#ifndef BaseLog_H
#define BaseLog_H

#include<cstdio>
#include<string>
#include<process.h>
#include<stdarg.h>
using namespace std;

#define DEBUG printf("[File:%s,Line:%d,Fun:%s] \n",__FILE__,__LINE__,__FUNCTION__)
//#define TRACE printf
#define LOG SetLine(__LINE__),SetFile(__FILE__),log

extern char *mfilename;
extern int mline;

void SetLine(int num);
void SetFile(char *filenm);
void log(const char* traceMessage, ...);

#endif




//tt.cpp

#include"tt.h"
#include"add.h"

int main(int argc,char *argv[])
{
long a=10000;
LOG("%d",argc);
for(int i=0;i<argc;i++)
{
LOG("%s,%ld",argv[i],a);
}
LOG("end");

int x=100,y=200;
CAdd myadd;
myadd.add(x,y);

return 0;
}

char *mfilename;
int mline;
void SetLine(int num)
{
mline=num;
};
void SetFile(char *filenm)
{
mfilename=filenm;
};
void log(const char* traceMessage, ...)
{
char chSendbuf[1025] = {0};
memset(chSendbuf, 0, 1024);

va_list ap;
va_start(ap, traceMessage);
vsprintf(chSendbuf, traceMessage, ap);
va_end(ap);

string Sendbuf;
int iBufLen = strlen(chSendbuf);
while ( iBufLen > 0 )
{
if ( chSendbuf[iBufLen-1]== '\n' || chSendbuf[iBufLen-1] == '\r' )
{
--iBufLen ;
continue ;
}
else
{
Sendbuf = chSendbuf+iBufLen ;
chSendbuf[iBufLen] = 0 ;
break ;
}
}
if ( Sendbuf.length() == 0 ) Sendbuf = "\n" ;

char tmp[2048] = {0};
if(mline > 1)
{
// Date nowtime = Date::GetCurrentTime();
// nowtime.toString();
// sprintf(tmp,"![%s](%d)[%d]%s %s%s",nowtime.toString().c_str(),GetFilelineNum(),getpid(),chSendbuf,Sendbuf.c_str());
sprintf(tmp,"(%d)[%s][Line:%d]%s %s",getpid(),mfilename,mline,chSendbuf,Sendbuf.c_str());
}
else if( mline == 1)
sprintf(tmp, "(%d)[%s][Line:%d]%s%s",getpid(),mfilename,mline,chSendbuf,Sendbuf.c_str());
else
sprintf(tmp, "(%d)[%s][Line:%d]%s%s",getpid(),mfilename,mline,chSendbuf,Sendbuf.c_str());

printf("%s\n",tmp);
};


//add.h

#ifndef Add_H
#define Add_H

#include"tt.h"

class CAdd
{
public:
CAdd() ;
virtual ~CAdd() ;
static int add(int a,int b);
};
#endif



//add.cpp

#include"add.h"

CAdd::CAdd()
{
}
CAdd::~CAdd()
{
}

int CAdd::add(int a,int b)
{
// LOG("%d,%d,sum=%d",a,b,a+b);
return a+b;
}
johnzhaobing 2009-08-17
  • 打赏
  • 举报
回复
up
HengStar 2009-08-17
  • 打赏
  • 举报
回复
[Quote=引用 23 楼 asksgp 的回复:]
用staic可以链接通过,但执行结果不对或者说不是我想要的。
[/Quote]

static在全局作用域中是限制声明变量在该文件域中使用,如果你在两个文件中声明
static int a;
这两个文件中的a并不是一个变量,所以也不会出现重定义

但是你具体要的功能并不清楚,最好的办法还是把实现部分分离到cpp文件中
lijian22500 2009-08-17
  • 打赏
  • 举报
回复
宏能定义函数吗,我觉的不妥,宏到可以定义假函数,见http://topic.csdn.net/u/20090804/00/204929c4-6b10-44cd-b112-5526dd101bd1.html
而且在同一个函数中也只能使用一次,要不然 变量有被多次定义了。
zjw6861982 2009-08-17
  • 打赏
  • 举报
回复
从来不在头文件定义函数及变量,因而从未遇到上述问题的路过。
lijian22500 2009-08-17
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 gongxinheng 的回复:]
引用 14 楼 asksgp 的回复:
现在是两个全局变量的问题,如何在不同的cpp文件调用宏的时候,宏里面使用的全局变量是指向当前cpp文件的?


1.建议不要用相同的全局变量名去定义全局变量
2.如果你非得这么做,而且确定这个全局变量只作用域当前cpp,你可以声明该全局变量时用static
3.可以考虑用命名空间

[/Quote]
(1)建议不要用相同的全局变量名,全局变量名能相同吗?
(2)让函数声明,变量声明限制在一个文件范围内,不失为一个好方法。所以才有的namespace吧!
lijian22500 2009-08-17
  • 打赏
  • 举报
回复
[Quote=引用 23 楼 asksgp 的回复:]
用staic可以链接通过,但执行结果不对或者说不是我想要的。
引用 17 楼 gongxinheng 的回复:
引用 14 楼 asksgp 的回复:
现在是两个全局变量的问题,如何在不同的cpp文件调用宏的时候,宏里面使用的全局变量是指向当前cpp文件的?


1.建议不要用相同的全局变量名去定义全局变量
2.如果你非得这么做,而且确定这个全局变量只作用域当前cpp,你可以声明该全局变量时用static
3.可以考虑用命名空间


[/Quote]
你怎么通过的??
asksgp 2009-08-17
  • 打赏
  • 举报
回复
用staic可以链接通过,但执行结果不对或者说不是我想要的。
[Quote=引用 17 楼 gongxinheng 的回复:]
引用 14 楼 asksgp 的回复:
现在是两个全局变量的问题,如何在不同的cpp文件调用宏的时候,宏里面使用的全局变量是指向当前cpp文件的?


1.建议不要用相同的全局变量名去定义全局变量
2.如果你非得这么做,而且确定这个全局变量只作用域当前cpp,你可以声明该全局变量时用static
3.可以考虑用命名空间

[/Quote]
lijian22500 2009-08-17
  • 打赏
  • 举报
回复
所以应该把 声明和 定义分开。分别是cpp文件和h文件。
加载更多回复(21)

65,187

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧