【问题标题】:Include Order and Hidden Dependencies包括顺序和隐藏的依赖项
【发布时间】:2017-05-30 08:49:55
【问题描述】:

在寻找有关包含顺序的最佳实践时,我偶然发现了这个线程:

C/C++ include file order/best practices [closed]

@squelart 表示,从本地包含到全局是更好的做法,因为这减少了隐藏依赖项的机会。我刚刚在一个 VS2015 项目中测试了这个,代码如下:

StrTest.h

#pragma once

class CStrTest
{
    public:
        CStrTest();
        ~CStrTest();

        std::string test;
};

StrTest.cpp

#include <string>
#include "StrTest.h"


CStrTest::CStrTest()
{
}

CStrTest::~CStrTest()
{
}

我无法重现所述行为(隐藏的依赖二重奏,包括 StrTest.cpp 中的第一个字符串)。编译器给了我多个错误。那么这是过去的事情还是我忽略了什么?

编辑:VS2015 编译器错误:

错误 C4430 缺少类型说明符 - 假定为 int。注意:C++ 不支持 default-int

错误 C2039 'string': is not a member of 'std'

错误 C3646 'test':未知的覆盖说明符

【问题讨论】:

  • 不清楚你在这里问什么 - 上面的代码编译。
  • 您实际上正在做与 squelart 答案建议相反的事情。
  • 您还需要在StrTest.h 中包含或至少转发声明std::string。你的头文件应该是自包含的。
  • @VTT 据我了解,这是 YokeM 的观点。他们正试图做相反的事情并通过隐式依赖重现问题 - 即即使不满足标头的所有依赖关系也能编译的程序。根据 YokeM 的说法,这个问题在 VS2015 中没有重现,它“给出了多个错误”。
  • @user2079303:谢谢,这就是我的意思。我还添加了 VS2015 编译器错误。

标签: c++ include dependencies


【解决方案1】:

所以这是过去的事情

不,隐藏的依赖项是标准行为,并且确实发生在现代编译器中。我不知道 VS,但 GCC 和 Clang 确实编译了您显示的程序而没有任何错误。演示:https://wandbox.org/permlink/ATJndwrOwirpDgDd

编译器给了我多个错误。

尽管“隐式”包含的风格很差,但就标准而言,只要保证隐式包含的文件被您或编写包含它的标头的人包含,它在技术上仍然是良好的 - 标准标头没有这样的保证。

因此,我反对将隐式包含视为错误的编译器功能。明确启用的警告会更合适。

【讨论】:

  • 谢谢,我没有用其他编译器测试这个。有趣的是,这适用于 GCC 和 Clang。
【解决方案2】:

我认为讨论的隐藏依赖问题的要点是,通常每个文件都包含其他几个文件,如果标题不是自包含的,那么在其他标题包含隐式依赖并破坏所有内容的情况下,包含它可能会起作用当其他标题更改和/或被移动/删除时。简而言之:使用带有隐藏依赖项的标头会导致代码极其脆弱。

// foo.hpp
#pragma once

#include <string> // if we remove this unrelated `StrTest.h` header will be broken
...

.

// main.cpp

#include "foo.hpp" // if we move this one line lower `StrTest.h` header will be broken
#include "StrTest.h" // accidentally works fine
...

【讨论】:

    猜你喜欢
    • 2014-08-20
    • 1970-01-01
    • 2023-03-24
    • 1970-01-01
    • 2016-05-18
    • 1970-01-01
    • 2012-10-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多