【问题标题】:C++ headers inclusion order, strange behaviourC++ 头文件包含顺序,奇怪的行为
【发布时间】:2021-11-23 10:34:30
【问题描述】:

我正在编写一些库,并希望有一些“可选”类方法(或只是函数),无论是否声明,都取决于其他库包含。

说,我有一个类SomeClass,方法是int foo(std::string)。有时,使用项目所基于的另一个库的类的类似方法也非常有用 - 例如,sf::StringwxString,相应地用于 SFML 或 wxWidgets。

在这种情况下,包括SFML/System.hpp 或更糟,wx/app.hpp 或类似的绝对是一个选项,因为我只想拥有已经的库的方法> 包括在内。因此,我的第一个示例必须(如我所想)可以正常工作,但事实并非如此:

main.cpp:

#include <SFML/System.hpp>       // FIRST, I include SFML base lib in the very first line.
#include <SFML/System/String.hpp>// to be 100% sure, I include SFML string class,
#include "a.h"                   // and ONLY AFTER that I include my own lib
// so inside the "a.h" file, the sf::String class *must* be already declared
main()
{   SomeClass x;
    x.foo("ABC");// error here: "undefined reference to `SomeClass::foo(sf::String)"
}

啊哈:

#ifndef A_H_INCLUDED
#define A_H_INCLUDED
class SomeClass
{   public:
    #ifdef SFML_STRING_HPP
    int foo(sf::String str);// this method is declared, as expected
    #endif
};
#endif

a.cpp:

#include "a.h"
#ifdef SFML_STRING_HPP
int SomeClass::foo(sf::String str)
{   return 1;
}
#endif

第一个问题是为什么a.cpp 一开始就包含a.h,而在a.h 内部,sf::String 声明的,那么为什么在a.cpp 之后 #include "a.h" 它实际上没有声明?

我尝试在a.cpp 文件中的#endif 指令之前添加#error OK,但此错误被触发。

我是否错过了有关 #include.cpp / .h 文件的内容?...

第二个问题是:如何解决或解决这个问题?

(是的,我每次都进行干净的重建以避免可能的编译器错误,因为部分更改源代码,g++ 喜欢它)。

P.S:相同类型的“依赖”方法声明与某些模板类完美配合 - 我想,这是因为实现在 .h 文件中,条件编译一切正常。

【问题讨论】:

  • 一点提示:您可以通过将#include 语句放入预处理器#ifdef 范围内来使它们成为可选语句。因此,您可以在声明和定义使用它的函数的相同条件下包含字符串头。
  • 根据上下文变化的类定义迟早会咬你。不要那样做。
  • 皮特,它为什么会咬人?我声明并定义了不同的 方法,所以在基于SFML 的项目中我将使用fooSM(sf::String),在基于wxWidgets 的项目中我将使用fooWX(wxString) 方法。这使我可以为许多不同的项目保持主库代码相同,并且还避免过多的类型转换(根据项目的基础库使用本机类型)。

标签: c++ include conditional-compilation


【解决方案1】:

a.c 包含不包含 的 a.h,因此未定义 SFML_STRING_HPP。通常,要包含的内容是通过编译器 -D 选项设置的。例如 -DUSE_SFML_STRING

main.cpp

#include <SFML/System.hpp>       // FIRST, I include SFML base lib in the very first line.
#include "a.h"                   // and ONLY AFTER that I include my own lib
// so inside the "a.h" file, the sf::String class *must* be already declared
main()
{   SomeClass x;
    x.foo("ABC");// error here: "undefined reference to `SomeClass::foo(sf::String)"
}

啊。

#ifndef A_H_INCLUDED
#define A_H_INCLUDED

#ifdef USE_SFML_STRING
#include <SFML/System/String.hpp>
#endif

class SomeClass
{   public:
    #ifdef SFML_STRING_HPP
    int foo(sf::String str);// this method is declared, as expected
    #endif
};
#endif

【讨论】:

  • 起初我以为一切都是从 main.cpp 开始编译的,包括必要的,但事实并非如此。添加项目范围的定义完全解决了我的问题。谢谢!
猜你喜欢
  • 1970-01-01
  • 2013-04-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-06
相关资源
最近更新 更多