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
C++ C++;头文件交叉#包括_C++_Header - Fatal编程技术网

C++ C++;头文件交叉#包括

C++ C++;头文件交叉#包括,c++,header,C++,Header,比如说,我有两个类:A&&B;一个头文件myheader.h: .... class A{ public: void display(B* c); }; class B{ public: void display(A* c); }; ..... 编译器给了我错误:“B”未按预期声明(在A::display中)。 因此,我为A和B分别编写了两个标题:aheader.h(包括A类的定义)和bheader.h(包括B类) 在aheader.h中: #include "bheader.

比如说,我有两个类:
A
&&
B
;一个头文件
myheader.h

....
class A{
public:
    void display(B* c);
};
class B{
public:
    void display(A* c);
};
.....
编译器给了我错误:“B”未按预期声明(在A::display中)

因此,我为
A
B
分别编写了两个标题:
aheader.h
(包括A类的定义)和
bheader.h
(包括B类)

aheader.h
中:

#include "bheader.h"
#include "aheader.h"
class B;

class A{
public:
    void display(B* c);
};
class A;

class B{
public:
    void display(A* c);
};
bheader.h
中:

#include "bheader.h"
#include "aheader.h"
class B;

class A{
public:
    void display(B* c);
};
class A;

class B{
public:
    void display(A* c);
};
到目前为止,一切顺利。 但是当我开始编写
实现时,问题就出现了。cpp

#include "aheader.h"
#include "bheader.h"
void A::display(B* c){}
void B::display(A* c){}
现在,A'尚未声明。(在B::display中)

我不知道如何简单地描述这个问题

我正在使用Ubuntu14、EclipseCDT、LinuxGCC和GNUMAKD构建器


我是C++新手,我猜这个问题是在链接时发生的。我真的希望有人能给我一个解释或解决办法。谢谢大家!

使用前向声明,而不是相互包含头文件。在
aheader.h
中:

#include "bheader.h"
#include "aheader.h"
class B;

class A{
public:
    void display(B* c);
};
class A;

class B{
public:
    void display(A* c);
};
bheader.h
中:

#include "bheader.h"
#include "aheader.h"
class B;

class A{
public:
    void display(B* c);
};
class A;

class B{
public:
    void display(A* c);
};

这在以C/C开头时很常见++

C++中常用的方法是将所有无关的类分开,每个类都在自己的头文件中。 始终(我是说,始终)头文件必须受到保护,防止递归包含。这是通过在头文件的开头追加一个IFDEF来完成的,因此该文件只包含一次:

即。文件aheader.h:

#ifndef __AHEADER_H__
#define __AHEADER_H__

//All the header code comes here...

#endif
因此,当包含头文件时,编译器将执行以下操作:

  • 是否定义了
    \uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
  • 它尚未定义,因此它编译头
  • 编译器现在定义
    \uuu AHEADER\u H\uu
  • 如果在任何其他点再次包含该文件:
  • 是否定义了
    \uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
  • 是的,不要再次编译头
  • 好的,这是你问题的一部分。但是让我们来看看你的实际问题

    出现错误是因为,正如编译器告诉您的,另一个类没有定义。换句话说,编译器不知道A(或B)是什么。 您不能将“aheader.h”包含在“bheader.h”中,因为这将抛出“B未定义”错误:

  • B领导将包括一名领导
  • 一个领导开始被处理
  • 找到了类A,它包含一个带有B参数的方法
  • 什么是B
  • 这里出错了 当然,如果以另一种方式包含它们(aheader.h包含在aheader.h中),错误将是“A未定义”,只是解释相同

    解决方案是什么

    只需向前定义类:

    在bheader.h中:

    #ifndef __BHEADER_H__
    #define __BHEADER_H__
    
    class A; //Forward definition. We don't have any member definition, just we are telling 
             //the compiler "Trust me, this is a class"
    
    class B{
    public:
       void display(A* c);
    }
    #endif
    
    同样的事情也必须在Header.h中进行

    最后,为了能够在实现代码中使用A或B,应该包含类的实际头文件

    文件implementation.cpp:

    #include "aheader.h"
    #include "bheader.h"
    void A::display(B* c){}
    //And so on...
    
    只要不需要完整的类定义(即),就可以使用转发声明:

    • 当类仅用作参数或函数的结果时
    • 当类仅与指针一起使用时
    当需要完整的类定义(即)时,不能有转发声明:

    • 当用作类成员时
    • 当继承它的时候
    顺便说一句,分离类的通常方法也是将每个类的实现分离为一个.cpp文件,最后有:

    • 领导
    • aheader.cpp
    • bheader.h
    • bheader.cpp

    首先,您需要在每个类中保护包含(这样在任何编译中不会包含多次),并预先声明作为函数参数的类型:

    aheader.h

    // This tells the precompiler only to incorporate this section if AHEADER_H is
    // not defined so it should only happen once, even if you include aheader.h
    // from many places.
    #ifndef AHEADER_H 
    #define AHEADER_H
    
    class B; // This tells the compiler that B is a class but it doesn't need to
             // know more than that now.
    
    class A{
    public:
        void display(B* c);
    };
    
    #endif
    
    #ifndef AHEADER_H
    #define AHEADER_H
    
    class A;
    
    class B{
    public:
        void display(A* c);
    };
    
    bheader.h

    // This tells the precompiler only to incorporate this section if AHEADER_H is
    // not defined so it should only happen once, even if you include aheader.h
    // from many places.
    #ifndef AHEADER_H 
    #define AHEADER_H
    
    class B; // This tells the compiler that B is a class but it doesn't need to
             // know more than that now.
    
    class A{
    public:
        void display(B* c);
    };
    
    #endif
    
    #ifndef AHEADER_H
    #define AHEADER_H
    
    class A;
    
    class B{
    public:
        void display(A* c);
    };
    
    不要把它们彼此分开,要把它们完全分开。然后,您应该能够以任何顺序包含它们

    接下来,您可能应该为每个类保留单独的实现文件:

    aimp.cpp

    #include <aheader.h>
    #include <bheader.h> // Compiler now needs B in full as this is the
                         // implementation
    
    void A::display(B* c)
    {
        // Some stuff
    }
    
    #include <aheader.h>
    #include <bheader.h> // Same here - the order is not important now.
    
    void B::display(A* c)
    {
        // Some stuff
    }
    
    最后一步是编译所有三个实现文件(
    .cpp
    ),然后链接到一个可执行文件中。祝你好运。

    这是因为当你包含一个文件时,它会被复制到源文件中。在首次包含您的实现之后。cpp将如下所示(还假定您使用了包含保护):

    第二次之后包括

    #ifndef _AHEADER_H_
    #define _AHEADER_H_
    
    #ifndef _BHEADER_H_
    #define _BHEADER_H_
    
    #include "bheader.h" 
    
    class B{ public:
        void display(A* c); 
    };
    #endif //_BHEADER_H_
    
    class A{ public:
        void display(B* c); 
    };
    #endif //_AHEADER_H_
    
    #include "bheader.h"
    
    void A::display(B* c){}
    void B::display(A* c){}
    
    第三个include也将放置bheader.h,但您的include防护将阻止它被执行

    正如你在B类的减让中所看到的,A类以前还没有被宣布过。如果要在同一个文件中定义两个类,可以执行以下操作:

    //File class_declarations.h
    
    #ifndef _CLASS_DECLARATIONS_H_
    #define _CLASS_DECLARATIONS_H_
    class B;
    
    class A{ public:
        void display(B* c); 
    };
    
    class B{ public:
        void display(A* c); 
    };
    
    #endif //_CLASS_DECLARATIONS_H_
    
    现在编译器知道有一个类B,它将在以后遇到它

    请注意,如果您尝试使用确切的类对象而不是指针,例如

    class A{ public:
        void display(B c); 
    };
    

    提前声明没有好处。还有其他方法可以克服这个问题。

    听起来像是一个声明依赖性问题,尽管这个问题不能完全由您上面给出的内容来确定。您需要完整地列出这些文件,或者至少列出一个显示问题的工作示例。well@Component10,我构建了一个全新的项目,包括main.cpp,它对这两个类没有做任何处理,还有一个myheader.h文件。一开始只有两个。在我得到错误之前,我删除了这个myheader.h文件并编写了aheader.h&&bheader.h和implementation.cpp文件。现在我有四个文件,包括main.cpp(仍然不做任何操作),我得到了相同的错误。哇!非常感谢您的详细回答!因此,解决方案很简单:单独实现!哈!我倾向于同意这一点,尽管它可以解决问题,尽管我以前不知道这一点。正如上面Component10所说,为每个类提供一个单独的实现将很好地完成这项工作。非常感谢大家!即使您正在分离实现文件sti