C++ 预处理器包含并定义多个文件的问题

Posted

技术标签:

【中文标题】C++ 预处理器包含并定义多个文件的问题【英文标题】:C++ Preprocessor include and define trouble with multiple files 【发布时间】:2012-08-03 16:18:52 【问题描述】:

我将抽象我的问题以避免包含不需要的细节,但如果需要,我可以提供源代码。我正在使用视觉工作室。

我有以下文件 - 所有头文件都有 #pragma 一次:

A.cpp //(包含我的主函数) B.h B.cpp //(不扮演任何角色) C.h C.cpp

这里是预处理器命令的设置方式:

A.cpp   #defines UseOptionOne
A.cpp   #includes B.h

B.h     #ifdef UseOptionOne   
            #defines Func as f1() //(calling a function that prints a msg)   
        #else                 
            #defines Func as [blank]  

A.cpp   #includes C.h
C.h     #includes B.h     // (B.h have #pragma once, so it doesnt get included again)

以下是函数调用的设置方式:

A.cpp   main function uses Func          //- It prints as intended 
A.cpp   calls function in C.cpp // this function does the following:
        
           #ifndef UseOptionOne
             exit(0)                    //- Doesn't happen, so UseOptionOne is defined
           #endif   
           uses Func                        //- DOES NOTHING?????
        
A.cpp   uses Func                       //- It prints as intended 

我不明白这怎么可能?确认 UseOptionOne 仍然在 C.h 中定义,但 Func 定义不同???

谁能解释一下?或者您希望我为您提供我相当复杂的解决方案或一些代码片段?

我真的迷路了:(

编辑:我使用断点来确认调用了 C.cpp 函数,'Func' 被简单地视为空白

EDIT2:由于缺乏声誉,我无法回答我自己的问题,所以我把它放在这里: 我创建了一个实现我的抽象描述的新项目,它确实触发了 #ifndef 中的退出 所以你们中的任何人都无法解决这个描述的问题。我将不得不再次查看所有内容并找到错误/错误。

【问题讨论】:

只是一个评论。为了代码可移植性,您可能应该使用包含保护而不是 #pragma once 我也是。在你上面的代码中你说'A.cpp #defines UseOptionOne'。在下面的解释中,您说“UseOptionOne 在 C.h 中定义”。它是哪一个?也许两者兼而有之。像这样解释你的代码的问题在于,你不可避免地会弄错一些关键细节,因此没有人能够回答你的问题。最好的办法是不要给我们摘录你的代码,也不要发布你的整个程序。最好的办法是制作一个仍然存在您描述的问题的代码的迷你版本,然后发布所有这些。 我同意 RageD 的观点,它总是更便于携带。根据我的经验,#pragma once 声明从未创造出如此多的优势,更喜欢它而不是便携。 我在下面的解释中的意思是 UseOptionOne 被确认在 C.h 中定义(仍然定义)!我的坏 【参考方案1】:

我的两分钱:

UseOptionsOne 仅针对 A.cpp 和包含 A.h 的类定义:在您的情况下,它仅在 A.cpp 中定义

C.cpp 没有引用 A.h,所以它看不到定义。在这种情况下,UseOptionOne 没有在 C.cpp 中声明, 它使用空白函数。

当你离开 C.cpp 的范围,并在 A.cpp 的范围内返回时,该函数可以工作,因为在那个范围内 UseOptionOne 已定义。

如果你想在所有文件中使用define,你可以创建一个单独的defines.h头文件并放入其中 定义,然后将该文件包含在您希望定义对其起作用的所有标头中。

【讨论】:

只是我的想法,但你打败了我,听起来像在 C.cpp 中定义 UseOptionOne 之前包含了 B.h 订单不会改变事情。 C 包含 B -> Func 在 C 中明确 - A 包含 B -> 定义更改 Func 结果是无论编译顺序如何,A 和 C 中的 Func 都不相同。简单地说,C 对定义的存在一无所知。如果所有文件都必须看到它,则必须声明该定义或在项目配置中,或通过一个全局头文件,该头文件必须包含在您想要该定义的每个头文件中。 如果是这种情况,exit(0) 将在 C.cpp 中触发,UseOptionOne 必须在函数中定义,但Func 必须为空才能生效提及。无论哪种方式,技术性,你所说的以更好的方式定义它仍然适用。 这是不正确的!首先没有A.h,没有人以任何方式包含A.cpp。 C.cpp 确实看到了 UseOptionOne 的定义,因为我使用了 #ifndef 而不是 #ifdef! 顺便说一句。将#define UseOptionOne 放在全局标题中的问题在于,我的库的用户应该在包含任何内容之前设置它

以上是关于C++ 预处理器包含并定义多个文件的问题的主要内容,如果未能解决你的问题,请参考以下文章

C 预处理器:包含基于定义

MS Visual Studio 2010 C++ 预处理器 - 如果函数在宏中定义并在其他地方调用,未定义时是不是有任何开销

预处理器定义在 VS2019 C++ 中不起作用

细节问题

有 C++ 标准库 ifdef 或 ifndef 预处理器指令吗?

CMake 对已定义(预处理器)头文件的依赖