C++ 前向声明与包含

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3632818/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 13:19:54  来源:igfitidea点击:

Forward Declaration vs Include

c++classforward-declaration

提问by Sii

Consider the following two scenarios (Edited just to complete the whole question and make it clearer)

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

Case 1: (doesnt compile as rightly mentioned below)

情况 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();
 }

Case 2: (the only modifications...works without compiliation error)

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

//B.h

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

Let us assume both the A.cpp and B.cpp are complied together. Do the above two scenarios make any differences? Is there a reason to prefer one method over the other?

让我们假设 A.cpp 和 B.cpp 一起编译。以上两种情况有什么区别吗?是否有理由更喜欢一种方法而不是另一种方法?

Edit: So how do I make scenario 1 work.

编辑:那么我如何使场景 1 工作。

采纳答案by Drew Hall

Case 1 will produce an "incomplete type" error when you compile B.cpp. Because class B contains a class A object, the definition (and in particular the size) of class A is required to be complete before the definition of class B.

情况 1 在编译 B.cpp 时会产生“类型不完整”错误。因为 B 类包含一个 A 类对象,所以 A 类的定义(尤其是大小)需要在 B 类定义之前完成。

Alternatively, you could choose to make some_variable a pointer or reference to class A, and in that case your forward declaration would be sufficient in B.h. You'd still need a full definition of A in B.cpp (assuming you made actual use of the A member functions/data).

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

回答by liaK

Forward declaration is not a substitute for Header file inclusion.

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

As the name itself implies, forward declaration is just a Declarationand not a definition.

顾名思义,前向声明只是 aDeclaration而不是 definition

So, you will declare saying the compiler that it is a class and I just declaring it here and will provide you the definition when am gonna use it. So, normally you forward declarein the Header file and #includein the .cpp file where you will usethe members of the forward declared class.

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

By doing so, what you make is, wherever you are including the header file there will just be a declaration for the class instead of the entire contents #included...

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

But having said that, when the compiler requires the definition of the class, it should be #included..

不过话说回来,当编译器要求定义类的时候,应该是#included..

So, in your case A obj;requires the definition of class Aand hence you should #include..

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

I myself asked a similar question hereand another similar questionwhich has also a nice answer...

我自己在这里问了一个类似的问题,另一个 类似的问题也有一个很好的答案......

Hope it helps..

希望能帮助到你..

回答by Hitesh

You need to use forward declarations in cases where you have classes that refer to each other.

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

//A.h

class B;

class A {
    B* someVar;
}

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

class B {
    A* someVar;
}

But there's no benefit for doing it in the case you laid out.

但是在您布置的情况下这样做没有任何好处。

回答by Mark Ransom

Think like a compiler. In order to create an Ainside of B, the compiler has to know how to build an A, and the only way to do that is to have the complete definition. The forward declaration tells the compiler that class Aexists without describing what it looks like; this is adequate for defining a pointer or a reference. When it comes time to use that pointer or reference, the complete class definition will be required.

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

回答by Arnold Spence

If you meant to portray some_variable as a pointer then the frequently recommended practice is to use forward declarations whenever possible to avoid the overhead of includes and longer compile times.

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

I'm all for best practices but I really like using IDEs that have nice code navigation features and forwards cause a problem there, at least with Netbeans. Whenever I try to navigate to a type declaration, I always end up at the forward and not the .h file containing the actual declaration. I'm willing to accept some extra compile time for the ease of navigation. Maybe this is just a problem with Netbeans :)

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

.. oh yeah.. If you look at the related questions to the right of your question, you will find lots of additional information of forward declarations.

.. 哦是的.. 如果您查看问题右侧的相关问题,您会发现很多关于前向声明的附加信息。

回答by mike

For case 1, compiler will complain with "incomplete type" for class B because class B contains a class A object, and you did not tell B any detail of class A, so compiler cann't decide the size of object B.

对于情况 1,编译器会抱怨 B 类的“类型不完整”,因为 B 类包含一个 A 类对象,而您没有告诉 B 类 A 的任何细节,因此编译器无法决定对象 B 的大小。

For your case, you can use A& objor A* objinstead of A obj, since the size of a reference/pointer is const(4/8 for 32bit/64bit CPU).

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