C++ headers 包含顺序,奇怪的行为

C++ headers inclusion order, strange behaviour

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

说,我有一个 class SomeClass 方法 int foo(std::string)。有时,使用项目所基于的另一个库的 classes 的类似方法也非常有用 - 例如,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)"
}

a.h:

#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:相同类型的“依赖”方法声明与某些模板 class 完美配合 - 我想,这是因为实现在 .h 文件中,所有内容都在好的关于条件编译。

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)"
}

a.h

#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