【问题标题】:Recommended C++ Include Practice推荐的 C++ 包含实践
【发布时间】:2021-09-18 04:52:26
【问题描述】:

在以下场景中,包含<string> 标头的最佳方法是什么?

main.cpp

#include "extra.h"

int main() {
    func("A string");
    return 0;
}

额外的.h

#ifndef EXTRA_H
#define EXTRA_H

    #include <string>

    void func(std::string);

#endif

额外的.cpp

#include <iostream>
#include "extra.h"

void func(std::string str) {
    std::cout << str << '\n';
}

【问题讨论】:

  • 您的代码看起来是正确的。你能更具体地谈谈你的问题吗?
  • 抱歉没有详细说明。我浏览了一些不同的教程,其中一些建议在 .cpp 文件中包含头文件,而不是依赖传递包含,因此我想知道是否应该在 extra.cpp 和 main 中添加 #include &lt;string&gt; 行。 cpp 也是如此。
  • 什么是“最好的”是相当主观的。就个人而言,作为一般规则,我包括我使用的东西,但在这种情况下,这可能更像是一种风格。如果相同的开发人员控制.h.cpp 文件,并且您知道extra.h 包含&lt;string&gt;,那么您可能认为将其包含在.cpp 中是可选的。但这只是我的看法。

标签: c++ include


【解决方案1】:

您的extra.h 包含&lt;string&gt;,因为它直接使用它。在您的main.cpp 中没有直接使用std::string,因此在其中包含&lt;string&gt; 会很奇怪。

此外,在extra.cpp 中包含&lt;string&gt; 是完全没有必要的,因为std::string 的使用是在您知道在extra.h 中声明的函数签名中,加上两个extra 文件的维护可以合理地预计会作为单个操作完成,所以不用担心extra.h 突然不包括&lt;string&gt; 然后打破extra.cpp,因为它们会一起维护。

【讨论】:

    【解决方案2】:

    头文件应包含尽可能少的内容。这使它保持干净,并且还允许更快的编译。如果头文件需要完整的类型,则必须在头文件中包含该类型的包含文件,否则使用前向声明。

    例如 ma​​in.h

    #pragma once
    
    // if your header uses a full type (see function h)
    // it needs to know the size of the type
    // then include header file for that type in your header
    
    #include <string>
    void h(std::string str);
    
    // if your header only has references or pointers to a type
    // then add a forward declaration of that type.
    // The compiler only has to know the size for the reference/pointer
    
    struct struct_t; 
    
    void f(const struct_t& s);
    void g(const struct_t* s);
    

    然后是 ma​​in.cpp

    #include "main.h"
    #include <iostream>
    // #include <string> not really needed already done in "main.h"
    
    // full declaration of struct_t in the place where it is needed.
    // note this could also be in done in its own header file. 
    struct struct_t
    {
        int value1;
        int value2;
    };
    
    void f(const struct_t& s)
    {
        std::cout << s.value1 << std::endl;
        std::cout << s.value2 << std::endl;
    }
    
    void g(const struct_t* s)
    {
        std::cout << s->value1 << std::endl;
        std::cout << s->value2 << std::endl;
    }
    
    void h(std::string s)
    {
        std::cout << s << std::endl;
    }
    
    int main()
    {
        struct_t values{ 0, 42 };
        f(values);
        g(&values);
        h("Hello World!");
    }
    

    【讨论】:

    • 将字符串包装在结构(结构、类等)中是否比在 extra.h 中包含 &lt;string&gt; 标头更有效?
    • 我为造成的混乱道歉,包装字符串不是我想要展示的,我更新了示例。
    • 如果您正在为客户端创建一组头文件,那么是的,对客户端隐藏复杂类型是一种有效的方法,但是我通常使用抽象基类(接口)和 pimpl 模式:en.cppreference.com/w/cpp/language/pimpl。但这不是你最初的问题:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多