Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/143.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
include语句应该驻留在哪里? 作为C++的返回新手,我尝试对包含方法进行排序。_C++_Include_Methodology - Fatal编程技术网

include语句应该驻留在哪里? 作为C++的返回新手,我尝试对包含方法进行排序。

include语句应该驻留在哪里? 作为C++的返回新手,我尝试对包含方法进行排序。,c++,include,methodology,C++,Include,Methodology,我遵循一套特定的指导原则,我在下面的示例中详细介绍了这些指导原则。到目前为止,这对我来说是可行的(整个项目一直在编译:),但我担心将来可能会遇到问题,因此我的问题是-这是一种正确的方法吗?有更好的吗?解释它的基本逻辑是什么? 考虑以下示例: 父亲.h #pragma once class Father { // Some implementation }; #pragma once #include "Father.h" #include "StructC.h" class Class

我遵循一套特定的指导原则,我在下面的示例中详细介绍了这些指导原则。到目前为止,这对我来说是可行的(整个项目一直在编译:),但我担心将来可能会遇到问题,因此我的问题是-这是一种正确的方法吗?有更好的吗?解释它的基本逻辑是什么?

考虑以下示例:

父亲.h

#pragma once
class Father
{
    // Some implementation
};
#pragma once
#include "Father.h"
#include "StructC.h"
class ClassB;
class ClassA : public Father
{
    StructC struct_c_obj;
    ClassB class_b_obj;
    // Some implementation
};
struct StructC {
    // Some implementation
};
ClassA.h

#pragma once
class Father
{
    // Some implementation
};
#pragma once
#include "Father.h"
#include "StructC.h"
class ClassB;
class ClassA : public Father
{
    StructC struct_c_obj;
    ClassB class_b_obj;
    // Some implementation
};
struct StructC {
    // Some implementation
};
ClassA.cpp

#include "Father.h"
#include "ClassB.h"
#include "StructC.h"
// Some implementation
ClassB.hClassB.cpp
没有包含的类

StructC.h

#pragma once
class Father
{
    // Some implementation
};
#pragma once
#include "Father.h"
#include "StructC.h"
class ClassB;
class ClassA : public Father
{
    StructC struct_c_obj;
    ClassB class_b_obj;
    // Some implementation
};
struct StructC {
    // Some implementation
};
我遵循这些准则:

  • 所有*.h均以
    #pragma once
    声明开头
  • 如果ClassA继承自类父,则必须将其同时包含在*.h和*.cpp文件中
  • 如果ClassA使用ClassB(并且在类的作用域中声明了一个ClassB变量),那么它有一个
    ClassB在ClassA.h中的减容,以及在ClassA.cpp中包含“ClassB.h”
  • 如果ClassA使用StructC(并且在类的作用域中声明了一个StructC变量),那么它必须将它同时包含在ClassA.h和ClassA.cpp中
  • 如果ClassA只在ClassA.cpp文件中使用ClassD或StructE,那么它应该只在那里包含它们
这可能是一套拙劣的指导方针,对基本逻辑了解甚少,所以我可能会感到愤怒。。。加油,我想在这里学习……)

更新:

  • 正如一些人在下面所写的,我在示例中有一个错误-只有当ClassA有一个指向ClassB的指针或引用,而不是当它有一个简单的ClassB数据成员时,才可以在ClassA中使用ClassB的前向声明

我从Python中得到的一件事(因为这是一个绝对的要求)是“在使用它的模块中导入(包括)它”。这将使您在有或没有定义时免于麻烦。

#pragma once
是非标准的(但得到广泛支持),因此您可能/可能不想使用
\ifdef
防护

至于是否需要
#包含任何特定的头,这取决于。如果代码只需要一个转发声明,那么通过转发声明类型来避免导入

除了模板之外,我认为在头文件中放置长函数定义可能不太合适


话虽如此,我认为
ClassA.h
实际上应该包括
ClassB.h
,因为
ClassA.h
的任何用户(可能使用
ClassA
)都必须拥有
ClassB.h
。好吧,如果它正在做类似于分配的事情。

以下是我个人遵循的准则:

  • 尽可能选择转发声明而不是包含。在您的情况下,
    ClassA
    包含一个
    ClassB
    ,因此需要一个
    #include“ClassB.h”
    。如果
    ClassB
    类型仅通过指针或引用出现在文件中,则向前引用就足够了
  • 使头文件“自给自足”:编译永远不应该依赖于包含的顺序,包含文件应该包含/转发需要解析的所有内容
  • 为确保遵守上述准则,请始终在
    ClassA.cpp
    中首先包含
    ClassA.h
    ,并对以下包含项使用任意顺序(我使用字母排序)
关于其他方面:

  • #pragma
    为非标准,首选
  • 请记住,永远不要转发声明标准类型:如果头文件中出现
    std::string
    ,则必须
    #包含
  • 如果您最终得到的头文件包含一百万个其他文件,那么您可能需要查看以减少依赖关系(本文还包含一些关于头文件的其他指南)

我通常一次都不使用
pragma
,因为pragma不是标准的。您可能必须将代码移植到未定义的其他编译器,并且必须使用
#ifndef#定义成语

这是因为我直接使用
#ifndef#定义

第二件事:在头文件中使用多个包含不是一个好主意:我总是尽量减少它们。如果你有太多的文件,每次你对其中一个文件做一点修改,你就必须重新编译每个依赖的.cpp文件


如果是这样的话,我采用piml习惯用法,你可以找到描述(见C++示例)。无论如何,如果项目的规模没有那么大,我认为您的方法是正确的。

当ClassA有这种类型的数据成员时,不要使用ClassB的前向声明。 当它有指向ClassB的指针时,可以使用它,如:

#pragma once 
#include "Father.h" 
#include "StructC.h" 
class ClassB; 
class ClassA : public Father 
{ 
    StructC struct_c_obj; 
    ClassB *class_b_obj; 
    // Some implementation 
}; 

关于你的回答,我有两个问题:1)为什么我们更喜欢远期申报?2) 我试图理解为什么不使用#pragma,为什么它不在标准中很重要?1)因为它减少了耦合(直接或间接包含头的任何文件在头更改时都必须重新编译)2)因为您可能希望有朝一日将代码移植到另一个编译器+1。这是一个很好的答案。我要补充的是,包含的顺序是:
ClassA.h
首先,然后是任何
ClassB.h
或您自己的其他类,然后是Boost头或其他库头,最后是标准库头(
string
vector
,等等)。遵循这个顺序有助于确保您自己的标题是自给自足的。您几乎不应该在头文件中包含完整的类定义。仅将转发声明头包含在