C++ 调用方法时的前向声明问题
我有一个问题,我认为与前向声明有关,但也许不是。
这是相关代码:
Ah
#ifndef A_H_
#define A_H_
#include "B.h"
class A
{
private:
B b;
public:
A() : b(*this) {}
void bar() {}
};
#endif /*A_H_*/
Bh
#ifndef B_H_
#define B_H_
#include "A.h"
class A;
class B
{
private:
A& a;
public:
B(A& a) : a(a) {}
void foo() { /*a.bar();*/ } //doesn't compile
};
#endif /*B_H_*/
main.cpp
#include "A.h"
int main()
{
A a;
return 0;
}
问题似乎出在 A::bar() 的调用上。 程序成功编译,直到我尝试调用此方法,此时我收到两个错误:
错误:无效使用不完整类型“struct A”
错误:“struct A”的前向声明
我认为这是因为 A::bar() 尚未定义或声明,因为两个标头相互引用。 然而,我转发了声明为 A 级的信息,但我不知道还需要做什么。 我是 C++ 新手,所以请原谅我。 我在网上其他地方找不到这个问题的答案。 一如既往,提前致谢!
I have a problem which I think is related to forward declarations, but perhaps not.
Here is the relevant code:
A.h
#ifndef A_H_
#define A_H_
#include "B.h"
class A
{
private:
B b;
public:
A() : b(*this) {}
void bar() {}
};
#endif /*A_H_*/
B.h
#ifndef B_H_
#define B_H_
#include "A.h"
class A;
class B
{
private:
A& a;
public:
B(A& a) : a(a) {}
void foo() { /*a.bar();*/ } //doesn't compile
};
#endif /*B_H_*/
main.cpp
#include "A.h"
int main()
{
A a;
return 0;
}
The problem seems to be with the invocation of A::bar(). The program successfully compiles until I attempt to call this method at which point I get two errors:
error: invalid use of incomplete type ‘struct A’
error: forward declaration of ‘struct A’
I presume this is because A::bar() has yet to be defined or declared since both headers reference each other. However, I forward declared class A and am at a loss as to what else I need to do. I am new to C++, so please forgive me. I could not find the answer to this question anywhere else online. As always, thanks in advance!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
你有一个循环引用,所以你需要分开 Bh 尝试类似:
Bh:
B.cpp:
编辑:解释为什么你需要将它分成两个文件:
类
B
包含一个对A
的引用,它可以是所谓的不完整类型。 您无法在其上调用任何函数,因为编译器还不知道A
到底是什么 - 它只知道它是某种类型的类。 一旦包含 Ah(在 .cpp 文件中),那么A
就是一个完整的类型,您可以用它做任何您喜欢的事情。您不能将整个内容保留在一个头文件中,因为您会得到循环引用。 您正在使用包含防护来防止无限循环,但您却得到了您不想要的东西。 当您编译 main.cpp 时,看看编译器最终会得到什么,就像您之前所做的那样:
You've got a circular reference, so you need to separate B.h. Try something like:
B.h:
B.cpp:
Edit: explanation for why you need to split it into two files:
The class
B
contains a reference toA
, which can be a so-called incomplete type. You can't call any functions on it because the compiler doesn't yet know what the heckA
is - it just knows that it's a class of some sort. Once you include A.h (in the .cpp file), thenA
is a complete type, and you can do whatever you like with it.You can't keep the whole thing in one header file because you'll get a circular reference. You're preventing an infinite loop with your include guards, but you're getting something you don't want. Look at what the compiler ends up with when you compile main.cpp, as you had it before:
#include
行将仅用file.h
的内容替换该行。 因此,当计算机尝试编译main.cpp
时,它会将所有内容整合在一起,如下所示。 在你想使用A::bar()的地方,它还没有被定义。The line
#include<file.h>
will just replace the line with the content offile.h
. So when the computer tries to compile yourmain.cpp
, it will pull everything together, which looks like the following. At the place you want to use A::bar(), it has not been defined.正如其他几个人提到的,循环引用似乎是您的问题。 另一个说法是“相互依赖”。 但是,我不会尝试找到正确的语法来编译和运行您的应用程序(我假设实际问题存在于比您发布的程序稍微高级的程序中),我会鼓励您从对象中解决问题 -面向设计的立场。
作为一般规则,应尽可能避免相互依赖。 我之前在自己的代码中遇到过这个问题(这导致了几天的调试,撕扯我的头发,并诅咒我的编译器),下面是我最终能够克服它的方法。 我将提出一个我自己的问题的淡化版本,作为如何解决该问题的具体示例,因此希望您能够提取出其背后隐藏的含义,并且最终一切都会有意义。
假设我们有两个类:Data 和 DataAnalyzer
Data 持有对 DataAnalyzer(用于分析数据)的引用,DataAnalyzer 持有对 Data(要分析的数据)的引用——相互依赖! 为了消除这种依赖性,我们从 DataAnalyzer 中提取出一个接口(在 C++ 中是纯虚拟类),该接口定义了 DataAnalyzer 所需的公共方法/属性。 它可能看起来像:
当我们定义 DataAnalyzer 时,我们这样做:
数据看起来像:
在你的控制器类中的某个地方,你可能有类似的东西:
现在,Data 独立存在(据我所知,IAalyzer 确实如此)不需要引用 Data),并且只有 DataAnalyzer 依赖于 Data。 如果你想继续下去,你可以继续删除DataAnalyzer对Data的依赖,但是为了简单地打破相互依赖,这应该足够了。
警告:我尚未对这段代码进行编译测试,因此可能需要一些细微的调整才能正确编译和运行。
祝你好运!
As several others have mentioned, the circular reference appears to be your problem. Another phrase for this would be "mutual dependency". However, rather than attempting to find the proper syntax to get your application to compile and run (I assume the actual problem exists in a program slightly more advanced than what you have posted), I would encourage you to attack the problem from an object-oriented design standpoint.
As a general rule, mutual dependencies should be avoided wherever possible. I've come across this issue in my own code before (which resulted in several days of debugging, ripping my hair out, and cursing my compiler), and here is how I was finally able to overcome it. I will present a watered down version of my own problem as a concrete example of how to address the issue, so hopefully you can extract out the hidden meaning behind it all, and it will all make sense in the end.
Let's say we have two classes: Data and DataAnalyzer
Data holds a reference to DataAnalyzer (used to analyze the data), and DataAnalyzer holds a reference to Data (the data to be analyzed) -- mutual dependency! In order to eliminate this dependency, we extract out an interface (in C++, a pure virtual class) from DataAnalyzer that defines the public methods/attributes required on DataAnalyzer. It might look something like:
When we define DataAnalyzer, we do it as follows:
And Data looks like:
Somewhere, in your controller class, you might have something like:
Now, Data stands by itself (as far as it knows, IAnalyzer does not require a reference to Data), and only DataAnalyzer is dependent on Data. If you want to keep going, you could continue to remove DataAnalyzer's dependency on Data, but for the sake of simply breaking the mutual dependency, this should be sufficient.
Warning: I have not compile tested this code, so it may require some minor adjustment to compile and run properly.
Good luck!
如果你真的希望 B::foo 内联,你可以在 Bh 中实现,尽管我不推荐它。
啊:
啊:
If you really want B::foo to be inline you could do the implementation in B.h, although I would not recommend it.
B.h:
A.h:
在 Bh 中,您包括 Ah 以及前向声明 A。
您需要将 Bh 分成 Bh 和 B.cpp,或者删除前向声明。
PS 你还有一个循环依赖。 Ah 包括 Bh,反之亦然。 不过,你的警卫已经发现了问题;)
In B.h, you are including A.h as well as forward declaring A.
You need to separate B.h into B.h and B.cpp, or remove the forward declaration.
PS You also have a circular dependency. A.h is including B.h, and vice versa. Your guards are catching the problem, though ;)
要添加到另一个答案(循环引用,这是正确的答案),如果您来自 C#/Java,请了解 C++ 是不同的,因为文件是按顺序解析的(而不是视为整体)。 因此,您需要小心确保所有内容都在使用之前按照包含文件的实际顺序进行定义(和/或根据需要将功能单独放入 .cpp 文件中)。
To add to the other answer (circular reference, which is the correct answer), if you're coming from C#/Java, understand that C++ is different, in that files are parsed in order (instead of considered as a whole). So you need to be careful to ensure that everything is defined before it is used, in the actual order that files are included (and/or separate functionality into .cpp files as appropriate).