今天用makefile, g++编译某个问题时遇到这么一个问题:
.a库里面包含一个fun函数, 但是这个fun函数有两个定义的实现, 而且它的实现是被放在了fun.h中, 两个实现分别被宏marco1和宏macro2区分, 如下:
fun.h:
class instance{
private:
int a;
public:
#if defined(marco1)
int fun(int n){return n;}
#elif defined(marco2)
int fun(int n){return n+1;}
#endif
};
在编译生成.a的时候,makefile中定义了宏-Dmarco1.
现在问题来了,我需要生成一个可执行文件main.bin,有一个main.cpp, 并且main.cpp中包含了#include fun.h, main函数需要引用这个.a中的fun, 能否直接这么玩?:
g++ main.cpp **.a -o main.bin
答案是否定的, 因为会报个这样的错误:说fun未定义!!!why?: 因为你在编译main.bin的时候,并没有定义任何宏呀,所以在编译.bin这个section的时候, 里面是没有任何fun定义的. 可能你会问, 那我.a里面已经定义了一个宏-Dmarco1的呀, .a里面应该是有一个fun的定义的呀. 但是切记, 编译器定义的宏, 是严格跟随文件走的!
怎么理解编译器定义的宏, 是严格跟随文件走的这句话呢, 就是说, 在编译.a的时候, 里面确实有定义宏-Dmarco1, 那么在.a里面, 确实存在着这么一个fun的定义, 但是因为在生成main.bin的时候, 因为main.cpp中包含了#include fun.h这句话, 那么编译器相当于在编译main.cpp的时候, 把#include fun.h展开了, 而且g++ main.cpp **.a -o main.bin在编译main.cpp的时候, 并没有包含宏-Dmarco1, 它就认为fun没有定义, 而且这里为什么说是宏是严格跟随文件走, 是因为即使在编.a的时候, 定义过宏-Dmarco1, 但是这个宏并不是跟随main.cpp走的, 因此在编译main.cpp的时候就认为没有这个定义.
那么, 能否这么玩呢? 虽然.a的库中定义了宏-Dmarco1, 但是我编.bin的时候却定义了宏-Dmarco2,如下:
g++ main.cpp **.a -Dmarco2 -o main.bin
这个是可以滴:
这样的话, 你会发现宏-Dmarco2覆盖了宏-Dmarco1, 在main函数中调fun()的时候, 它返回的是-Dmarco2中括起来的函数, 即会返回n+1. 还是遵循"编译器定义的宏, 是严格跟随文件走的"这个定律, 因为编main.cpp, 跟随了一个-Dmarco2, 这样, 即使编.a的时候定义了宏-Dmarco1, 但这个宏不是跟随main.cpp的, 因此没起作用, 被-Dmarco2覆盖了.
再把文件改成下面这样, 把fun的定义和声明分开, 声明依然放在类里, 定义放在cpp里面:
fun.h:
class instance{
private:
int a;
public:
int fun(int n);
};
fun.cpp:
#if defined(marco1)
int fun(int n){return n;}
#elif defined(marco2)
int fun(int n){return n+1;}
#endif
这个时候, 仍然在编.a的时候, 定义宏-Dmarco1, 编main.bin的时候, 定义宏-Dmarco2, 这个时候在main中再调用fun的时候, 会发现返回的是宏-Dmarco1扩住的函数, 因为在编main.cpp的时候, 虽然定义了宏-Dmarco2, 但因为fun.h中并没有对这个宏的引用, main.cpp包含了fun.h, 经扩展后的文件里面没有宏宏-Dmarco2, 所以定义的-Dmarco2并没有跟着文件走, 跟着文件走的是-Dmarco1, 所以最后返回的调用函数是被宏-Dmarco1括起来的fun.
阅读(4744) | 评论(0) | 转发(0) |