关于C ++预处理器,使用#define有条件地排除主函数

时间:2010-10-26 00:03:32

标签: c++ macros c-preprocessor

情况如下: 我有三个文件,Test1.cpp和Test2.cpp。 Test1.cpp可以按原样编译到独立的应用程序中。 Test1.cpp还包含一些我想在Test2.cpp中重用的函数。我正在使用#ifndef #endif块来有条件地排除Test1.cpp的主要功能,这样当我编译Test2.cpp时,Test2.cpp中的main函数将能够调用Test1.cpp中定义的函数。示例代码:

--------------------------------------------
//File: Test1.h
#include <iostream>
void do_something();
--------------------------------------------
//File: Test1.h
#include "Test1.h"
void do_something();
{
  std::cout<<"Done"<<std::endl;
}
#ifndef FN_MAIN
int main()
{
  do_something();
  return 0;
}
#endif
--------------------------------------
//File: Test2.cpp
#define FN_MAIN
#include "Test1.h"
int main()
{
  do_something();
  return 0;
}
--------------------------------------

使用Test1.cpp调用g ++工作正常并且行为符合预期,但是使用Test2.cpp和Test1.cpp调用g ++失败,因为main被多次定义。但是,使用-DFN_MAIN和两个源文件调用g ++可以解决此问题。有没有办法解决这个问题?我认为这个问题来自我对C ++预处理器的不完全理解。

注意:我这样做的动机是减少我正在处理的项目代码的大小。实际项目包括一个独立版本的Test1.cpp和其他几个使用Test1.cpp函数的程序。

2 个答案:

答案 0 :(得分:5)

预处理器按顺序运行每个源文件。在一个.cpp文件中定义的宏不会影响在另一个.cpp文件中定义的宏。

一个选项是在标题中定义FN_MAIN:然后当Test1.cpp包含该标题时,宏仍将被定义。但是,我认为在命令行上定义宏可能更简洁;这取决于你的具体用例。

另一种选择是将Test1.cpp main()移动到单独的.cpp文件中,并使用它构建单独的可执行文件。

答案 1 :(得分:2)

要以这种方式解决您的问题,您应该在Test2.cpp中使用#include "Test1.cpp"而不是包含Test1.h,然后只使用Test2.cpp调用g ++。这样你就可以编译一个编译单元,它包含来自Test1.cpp和Test2.cpp的所有源代码。

然而 - 这是一个非常糟糕的主意,所以不要这样做。

您应该做的是将实用程序功能组织到单个文件中,例如,最初只在一个文件Common.cpp中使用头文件Common.h来保持简单。然后编译并将这些文件链接到您将要创建的每个可执行文件中。这是正确的方法,它更容易理解和使用,并且使用多个源文件不会让你的应用程序更大。

在你的情况下,将你的常用方法移动到说Common.cpp / h后,你会做这样的事情:

g++ Test1.cpp Common.cpp  # to build Test1.exe
g++ Test2.cpp Common.cpp  # to build Test2.exe