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++ 预处理器包含并定义多个文件的问题的主要内容,如果未能解决你的问题,请参考以下文章
MS Visual Studio 2010 C++ 预处理器 - 如果函数在宏中定义并在其他地方调用,未定义时是不是有任何开销