【问题标题】:Swap out generally used functions in C++交换 C++ 中常用的函数
【发布时间】:2011-05-10 08:04:09
【问题描述】:

你好, 我目前在 C++ 中有一个很大的代码文件,其中包含许多我经常在不同版本的程序中使用的函数,所以我考虑换掉常用的函数:例如我有:

void doSomething(mxArray *in)
{
    mexPrintf("Hello Matlab");
}

mxArraymexPrintf 是在另一个来自 matlab (mex.h) 的文件中定义的。在我现在拥有的主文件中:

#include "mex.h"
#include "_general.h"

我想知道在_general.cpp 中不包含mex.h 时我没有收到任何编译器错误,这也是因为文件本身显然需要它。在这种情况下,在 mex.h 已经包含在主文件中之后,您会更好地进行包含还是不重要?

谢谢!

【问题讨论】:

  • 你使用的是预编译头文件吗?

标签: c++ header include


【解决方案1】:

C++(与 C 不同)将拒绝对尚未看到声明的函数的签名做出可疑的假设,并且编译将失败并显示错误消息。如果您没有收到错误,则某些标头正在获取该函数的声明。如果找不到,请尝试仅运行预处理器阶段(例如,对于 GCC,您将使用 g++ -E)并检查输出以查看声明...您的编译器可能会留下有关哪个文件包含位的 cmets有助于理解情况的代码。

例如,如果 _general.cpp 包含包含 mex.h 的 _general.h,那么这是可行的,无需直接从 _general.cpp 包含它。但是,如果它可以从 _general.h 中删除,因为它只在“general”的实现中需要,那再好不过了。

如果其他一些代码,比如“libraryX”使用 mex.h 来满足其内部需求,而不通过其公共 API 公开与 mex 相关的功能,那么最好不要假设它会继续为您包含 mex.h 并包含它自己。

【讨论】:

  • 好的,谢谢。请让我问一下一般的编译:所以我最好将 mex.h 包含在 _general.h 和 _general.c 中,对吗?在matlab中通过'mex'编译它时,我只需要列出所有文件名,例如'mex mainfile.c _general.c' 或者如何正确编译它以便 mainfile 使用 _general.c?还是我首先必须只编译 _general.c 而不是以某种方式使用“对象”,例如mex mainfile.c -o _general.o
  • “我最好将 mex.h 包含在 _general.h 和 _general.c 中,对吗?”...不 - 如果在 _general.h 未包含 mex.h 时出现错误,请包含它那里而且只有那里,否则只能从 _general.cpp 中包含它;所以,一次就足够了,如果可能的话 .c 会更好。我不知道“mex”是什么,也从未使用过 matlab。如果您使用的是标头,那么您必须包含一些 mex 库。 “mex”可能是调用 C++ 编译器并提供该库的包装器,我无法猜测,您需要查看 mex 的文档。
  • 如果你知道要使用哪个库文件,你可以尝试自己使用g++ -I/mexpath/include -o general.o general.c,然后g++ -o mainfile mainfile.c general.o -L/mexpath/lib -lmex)
【解决方案2】:

正如 Tamás 所指出的,#include 指令实际上将头文件包含到您的源代码中。您可以使用预处理器(gcc 的一部分)进行检查

$ cat a.cpp
#include "b.h"
int main() {
    return b();
}
$ cat b.h
#ifndef _B_H
#define _B_H

int b()
{
    return 0;
}

#endif
$ cpp a.cpp
# 1 "a.cpp"
    # 1 "<built-in>"
# 1 "<command-line>"
# 1 "a.cpp"
# 1 "b.h" 1



int b()
{
    return 0;
}
# 2 "a.cpp" 2
int main() {
    return b();
}
$

如您所见,如果您包含两次相同的文件(在涉及多个源文件的任何中等复杂的程序中经常出现这种情况),您会遇到将相同的函数定义两次的问题。为了解决这个问题,标准的方法是使用'include guards' (#ifndef, #define and #endif in b.h)。这样,每当您包含 b.h 时,都会定义一个常量。当您再次包含 b.h 时,预处理器会检查此常量并决定不再包含它。

当然,在选择常量的名称时应该小心:)

如果您遵循此规则,您可以理想地在任何地方包含任何头文件。在绝对必要的地方包含头文件通常是个好主意,否则编译将失败。此外,一个好的做法是在自定义头文件之前包含标准头文件。

HTH!

【讨论】:

  • “好的做法是在自定义头文件之前包含标准头文件” - 这也是我所做的(尽管我不知道它是好的做法的任何逻辑理由)except 当某个文件x.c++ 包含它自己的头文件x.h 时,在这种情况下它应该首先包含它自己的头文件。这确保了如果 x.h 依赖于 x.c++ 巧合包含的某些内容,它仍必须包含它本身,以便 x.c++ 构建到 x.o|so|a|dll 中。最好自己发现这种依赖bug,而不是让x.h的客户端代码发现它....
猜你喜欢
  • 2016-04-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-15
  • 2022-11-19
  • 2020-03-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多