【问题标题】:Is it possible to add an include directive inside of a class definition?是否可以在类定义中添加包含指令?
【发布时间】:2021-10-13 15:13:53
【问题描述】:

我目前正在开展一个项目,我们有一组共享的标题。现在我们想添加一些私有字段,而不必将这些声明直接放在共享标头中。

有人提出以下问题:

namespace something {
    class Foo {
    public:
        Foo();

        void doFoo();
    private:
#if __has_include("foo_private.hpp")
#include "foo_private.hpp"
#endif
    };
}

_private.hpp 标头中,我们将放置该类的私有字段。当只有默认数据类型(int、bool 等)时,这可以正常工作(ish)。但是,只要您在 _private.hpp 文件中添加一个包含,例如 #include,一切都会中断。

它给出了以下错误expected unqualified-id before ‘namespace’,据我了解,这是非常合乎逻辑的,因为您试图在类中定义命名空间。

示例 _private.hpp 文件

#ifndef DUMMY_PRIVATE_TEMPLATE_INCLUDES_FOO_PRIVATE_HPP
#define DUMMY_PRIVATE_TEMPLATE_INCLUDES_FOO_PRIVATE_HPP

#include <string>

int mySecretNumber;

std::string mySecretString;

#endif

现在我的问题是,有没有办法欺骗预处理器,或者以某种方式使用不同的解决方案获得相同的结果?

【问题讨论】:

  • 请不要将 HTML/CSS/JS sn-ps 用于非 HTML/CSS/JS 代码。
  • 糟糕,非常抱歉
  • 可以,但不能将#include &lt;string&gt; 放在类定义中。 Now we want add some private fields without having to put those declarations directly in the shared headers. 那要么是继承,要么是 pimpl 成语。在任何一种情况下,将#include 放在类定义的中间都将难以维护。
  • 您要解决的实际问题是什么?您说您不希望公共标头中出现成员变量,但为什么呢?
  • 如果这是试图将实现细节隐藏在一个私有的未受干扰的标头中,它注定会失败。 C++ 对象模型要求各处的所有代码都可以看到相同的类布局。 pimpl 成语可能是你应该研究的东西。

标签: c++ c-preprocessor


【解决方案1】:
namespace something {
    class Foo {
    public:
        Foo();

        void doFoo();
    private:
#if __has_include("foo_private.hpp")
#include "foo_private.hpp"
#endif
    };
}

如果该代码包含如下所示的文件:

#ifndef DUMMY_PRIVATE_TEMPLATE_INCLUDES_FOO_PRIVATE_HPP
#define DUMMY_PRIVATE_TEMPLATE_INCLUDES_FOO_PRIVATE_HPP

#include <string>

int mySecretNumber;

std::string mySecretString;

#endif

然后你会得到这个(虽然实际上,#includes 本身会解析为&lt;string&gt; 等的内容):

namespace something {
    class Foo {
    public:
        Foo();

        void doFoo();
    private:
        #ifndef DUMMY_PRIVATE_TEMPLATE_INCLUDES_FOO_PRIVATE_HPP
        #define DUMMY_PRIVATE_TEMPLATE_INCLUDES_FOO_PRIVATE_HPP

        #include <string>

        int mySecretNumber;

        std::string mySecretString;

        #endif
    };
}

也许这表明了您的问题?您在类的中间包含“字符串”,但它需要包含在文件的全局命名空间范围内。

相反,在外部标头的顶部包含字符串,不要在私有标头中使用包含保护,并且仅将要粘贴到类中的代码主体放入该私有标头中。出于这个原因,您可能不会将其称为“.hpp”文件,而是使用其他名称来明确它不是正常的标头。

此外,__has_include 功能似乎值得怀疑,因为如果您的私有标头丢失,您可能不希望它编译为空类。

更糟糕的是,如果您编译某个找到标头的翻译单元,然后编译另一个找不到私有标头的翻译单元,您最终会得到您的类的两个不同定义,这违反了一个定义规则——是未定义的行为,不需要诊断。非常讨厌的东西(假设你的构建完全成功。)

我不是这种隐藏的忠实拥护者,因为它会使编辑器难以正确显示您的代码、为您的私有标题着色和索引,或者以其他方式以正常方式处理代码。您可能会考虑查看 PIMPL 习惯用法,以将类的实现隐藏在其 .cpp 文件中,这样头文件的用户根本不必看到它。

【讨论】:

    猜你喜欢
    • 2021-07-12
    • 2022-10-18
    • 1970-01-01
    • 2017-01-06
    • 2021-04-29
    • 1970-01-01
    • 1970-01-01
    • 2021-06-30
    • 1970-01-01
    相关资源
    最近更新 更多