前向声明与包含
考虑以下两种情况(编辑只是为了完成整个问题并使其更清晰)
案例 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 发挥作用呢?
Consider the following two scenarios (Edited just to complete the whole question and make it clearer)
Case 1: (doesnt compile as rightly mentioned below)
//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)
//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?
Edit:
So how do I make scenario 1 work.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
前向声明不能替代头文件包含。
顾名思义,前向声明只是一个
声明
而不是定义。因此,您将声明编译器它是一个类,我只是在这里声明它,并在我要使用它时为您提供定义。因此,通常您在头文件中
转发声明
,并在 .cpp 文件中#include
,您将在其中使用转发声明的类的成员。通过这样做,你所做的是,无论你在哪里包含头文件,都只会有一个类的声明,而不是整个内容
#included
...但是话虽如此,当编译器需要类的定义,它应该是
#included
..因此,在您的情况下
A obj;
需要class A
的定义并且因此你应该#include
..我自己也问过类似的问题这里< /a> 和另一个 类似问题 也有一个很好的答案......
希望它帮助..
Forward declaration is not a substitute for Header file inclusion.
As the name itself implies, forward declaration is just a
Declaration
and not a 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 declare
in the Header file and#include
in the .cpp file where you will use the members of the forward declared class.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
...But having said that, when the compiler requires the definition of the class, it should be
#included
..So, in your case
A obj;
requires the definition ofclass A
and hence you should#include
..I myself asked a similar question here and another similar question which has also a nice answer...
Hope it helps..
情况 1 在编译 B.cpp 时会产生“类型不完整”错误。因为类 B 包含类 A 对象,所以类 A 的定义(特别是大小)需要在类 B 的定义之前完成。
或者,您可以选择将 some_variable 设为类 A 的指针或引用,并且在这种情况下,您的前向声明在 Bh 中就足够了,您仍然需要 B.cpp 中 A 的完整定义(假设您实际使用了 A 成员函数/数据)。
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.
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).
如果您的类相互引用,则需要使用前向声明。
但在你提出的情况下这样做没有任何好处。
You need to use forward declarations in cases where you have classes that refer to each other.
But there's no benefit for doing it in the case you laid out.
像编译器一样思考。为了在
B
内部创建A
,编译器必须知道如何构建A
,而唯一的方法是以获得完整的定义。前向声明告诉编译器类A
存在,但没有描述它的样子;这足以定义指针或引用。当需要使用该指针或引用时,将需要完整的类定义。Think like a compiler. In order to create an
A
inside ofB
, the compiler has to know how to build anA
, and the only way to do that is to have the complete definition. The forward declaration tells the compiler that classA
exists 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.如果您打算将 some_variable 描述为指针,那么经常推荐的做法是尽可能使用前向声明,以避免包含的开销和更长的编译时间。
我完全支持最佳实践,但我真的很喜欢使用具有良好代码导航功能的 IDE,并且转发会导致问题,至少对于 Netbeans 来说是这样。每当我尝试导航到类型声明时,我总是会到达前面,而不是包含实际声明的 .h 文件。为了便于导航,我愿意接受一些额外的编译时间。也许这只是 Netbeans 的问题:)
.. 哦是的.. 如果您查看问题右侧的相关问题,您会发现许多前向声明的附加信息。
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.
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 :)
.. 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.
情况1,编译器会抱怨B类“类型不完整”,因为B类包含一个A类对象,而你没有告诉B类A的任何细节,所以编译器无法决定对象B的大小。
对于 这种情况,你可以使用
A& obj
或A* obj
而不是A obj
,因为引用/指针的大小是 const(32 位/64 位 CPU 为 4/8)。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.
For your case, you can use
A& obj
orA* obj
instead ofA obj
, since the size of a reference/pointer is const(4/8 for 32bit/64bit CPU).