前瞻声明与包含

时间:2010-09-03 03:11:03

标签: c++ class forward-declaration

考虑以下两种情况(编辑只是为了完成整个问题并使其更清晰)

案例1 :(没有正确编译,如下所述)

//B.h
#ifndef B_H
#define B_H
#include "B.h"

class A;

class B { 
        A obj;
        public:
        void printA_thruB();

         };  
#endif

//B.cpp
#include "B.h"
#include <iostream>

void B::printA_thruB(){
        obj.printA();
        }   


//A.h;
#ifndef A_H
#define A_H

#include "A.h"

class A { 
        int a;
        public:
        A();
        void printA();

         };  
#endif   

//A.cpp                           
#include "A.h"                    
#include <iostream>               

A::A(){                           
        a=10;                     
        }                         

void A::printA()                  
{                                 
std::cout<<"A:"<<a<<std::endl;    
}  


//main.cpp
 #include "B.h"
  #include<iostream>
 using namespace std;

 int main()
 {
 B obj;
 obj.printA_thruB();
 }

案例2 :(唯一的修改......没有编译错误)

//B.h

#include "A.h" //Add this line
//class A;     //comment out this line

让我们假设A.cpp和B.cpp都被编译在一起。上述两种情况是否存在差异?是否有理由偏好另一种方法?

编辑: 那么如何让场景1工作呢。

6 个答案:

答案 0 :(得分:13)

编译B.cpp时,情况1将产生“不完整类型”错误。因为B类包含A类对象,所以A类的定义(特别是大小)必须在B类定义之前完成。

或者,您可以选择将some_variable作为指针或对A类的引用,在这种情况下,您的前向声明在B.h中就足够了。你仍然需要B.cpp中A的完整定义(假设你实际使用了A成员函数/数据)。

答案 1 :(得分:10)

前向声明不能替代包含头文件。

正如名称本身所暗示的那样,前向声明只是Declaration 而不是定义

因此,您将声明编译器说它是一个类,我只是在这里声明它并将在何时使用它时为您提供定义。因此,通常是Header文件中的forward declare和.cpp文件中的#include,您将使用前向声明的类的成员。

通过这样做,你所做的是,无论你在哪里包括头文件,都只会有一个类的声明而不是整个内容#included ......

但话说回来,当编译器需要定义类时,它应该是#included ..

因此,在您的情况下A obj;需要class A的定义,因此您应该#include ..

我自己问了一个类似的问题here和另一个similar question,这也有一个很好的答案......

希望有所帮助......

答案 2 :(得分:4)

如果你有相互引用的类,你需要使用前向声明。

//A.h

class B;

class A {
    B* someVar;
}

//B.h
#include <A.h>

class B {
    A* someVar;
}

但是在你布置的情况下做这件事没有任何好处。

答案 3 :(得分:3)

像编译器一样思考。为了在A内创建B,编译器必须知道如何构建A,唯一的方法是获得完整的定义。前向声明告诉编译器类A存在而不描述它的外观;这足以定义指针或引用。当需要使用该指针或引用时,将需要完整的类定义。

答案 4 :(得分:2)

如果您打算将some_variable描述为指针,那么经常建议的做法是尽可能使用前向声明,以避免包含的开销和更长的编译时间。

我都是最佳实践,但我真的很喜欢使用具有良好代码导航功能的IDE,并且前端会导致问题,至少对于Netbeans而言。每当我尝试导航到类型声明时,我总是在前面而不是包含实际声明的.h文件。我愿意接受一些额外的编译时间以便于导航。也许这只是Netbeans的一个问题:)

..哦是的..如果你查看问题右边的相关问题,你会发现许多关于前瞻性声明的其他信息。

答案 5 :(得分:0)

对于案例1,编译器会抱怨&#34;不完整类型&#34;对于B类,因为B类包含一个A类对象,并且您没有告诉B任何A类的细节,因此编译器无法确定对象B的大小。

对于您的情况,您可以使用A& objA* obj而不是A obj,因为引用/指针的大小是const(32位/ 64位CPU为4/8)。