类的前向声明似乎在 C++ 中不起作用;
以下代码是在VC++6中编译的。我不明白为什么我在以下代码中收到编译错误 C2079: 'b' 使用未定义的类 'B'
。
B 类源
#include "B.h"
void B::SomeFunction()
{
}
B 类标头
#include "A.h"
struct A;
class B
{
public:
A a;
void SomeFunction();
};
struct A 标头
#include "B.h"
class B;
struct A
{
B b;
};
如果我将 B 类标头更改为以下内容,则不会出现错误。但标头声明不会位于顶部!
带有奇怪标头声明的 B 类标头
struct A;
class B
{
public:
A a;
void SomeFunction();
};
#include "A.h"
The follwing code is compiled in VC++6. I don't understand why I am getting the compilation error C2079: 'b' uses undefined class 'B'
for the following code.
Class B Source
#include "B.h"
void B::SomeFunction()
{
}
Class B Header
#include "A.h"
struct A;
class B
{
public:
A a;
void SomeFunction();
};
struct A Header
#include "B.h"
class B;
struct A
{
B b;
};
If I changed class B header to the following, then there will be no error. But the header declaration won't be at the top!
Class B Header with weird header declaration
struct A;
class B
{
public:
A a;
void SomeFunction();
};
#include "A.h"
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
为了定义一个类或结构,编译器必须知道该类的每个成员变量有多大。前向声明不会执行此操作。我只见过它用于指针和(较少)引用。
除此之外,您在这里尝试做的事情无法完成。您不能拥有一个包含类 B 的对象的类 A,而该类 B 又包含类 A 的对象。但是,您可以拥有类A 包含一个指向类 B 的指针,而类 B 包含类 A 的对象。
B.cpp
Bh
啊
两点。首先,请确保使用某种形式的幂等性来防止每个编译单元多次包含标头。其次,了解在 C++ 中,类和结构之间的唯一区别是默认可见性级别 - 类默认使用私有可见性,而结构默认使用公共可见性。以下定义在 C++ 中功能等效。
In order to define a class or struct, the compiler has to know how big each member variable of the class is. A forward declaration does not do this. I've only ever seen it used for pointers and (less often) references.
Beyond that, what you're trying to do here cannot be done. You cannot have a class A that contains an object of another class B that contains an object of class A. You can, however, have class A contain a pointer to class B that contains an object of class A.
B.cpp
B.h
A.h
Two points. First, be sure to use some form of idempotence to keep the headers from being included multiple times per compilation unit. Second, understand that in C++, the only difference between classes and structs is the default visibility level - classes use private visibility by default while structs use public visibility by default. The following definitions are functionally equivalent in C++.
前向声明,例如
或
将 A 作为不完整类型引入,并且在到达类型定义末尾之前它保持不完整状态。对于不完整的类型,有些事情可以做,有些事情不能做。您可以
您不能
在代码中,您尝试声明不完整类型的结构成员。这是非法的。仅允许指针和引用。
Forward declarations, like
or
Introduce A as an incomplete type and it remains incomplete until end of type's definition is reached. There are things you can do with incomplete types and things you can't. You can
You can't
In your code you try to declare struct member of incomplete type. It's illegal. Only pointers and references are allowed.
您正在尝试仅使用前向声明创建 A 的对象。此时编译器(仅使用前向 decl)无法决定对象 A 的大小,因此无法分配 A 所需的内存。因此,您无法仅使用前向 decl 创建对象。
相反,替换为:
没有 A 的类定义的对 A 的指针或引用将可以正常工作。
You are trying to create the object of A with only forward declaration. Compiler at this moment ( with only forward decl) cannot decide the size of the object A and hence, it cannot allocate memory required for A. So you cannot create objects with only forward decl.
Instead replace with:
Pointer or reference to A without A's class definition will work fine.
这里有两个问题引起了我的注意。
1:您编写了
Struct A
而不是struct A
;注意小写的“s”。您的编译器可能会考虑等效项,但我不认为它是标准 C++。您已在
A
和B
之间定义了循环引用。每个 A 对象必须包含一个B
对象,但每个B
对象必须包含一个A
对象!这是一个矛盾,并且永远不会按照你想要的方式进行。解决该问题的常用 C++ 方法是使用 A::b 或 B::a(或两者)的指针或引用。Two issues jump out at me here.
1: You've written
Struct A
instead ofstruct A
; note the lower-case "s". Your compiler might consider the equivalent, but I don't think it's standard C++.You have defined a circular reference between
A
andB
. Each A object must contain aB
object, but eachB
object must contain anA
object! This is a contradiction, and will never work the way you want it to. The usual C++ way to solve that problem is to use pointers or references forA::b
orB::a
(or both).您还可以包含来自 Bh 的 Ah 和来自 Ah 的 Bh 您至少应该使用预处理器宏:
这样该文件就不会被包含多次。
You alse include A.h from B.h and B.h from A.h. You should at least use preprocessor macros:
so that file won't be included more than once.
如果您创建 A 的实例,则会创建 B 的实例(成员 var),B 的实例将创建 A 的实例(成员 var),B 的实例将创建 B 的实例,B 的实例将创建 A 的实例,依此类推...
编译器不应允许这样做,因为它需要无限的内存。
为了解决这个问题,A 或 B 必须使用另一个类的引用/指针。
If you create an instance of A, that will create an instance of B (member var) which will create an instance of A (member var) which will create an instance of B which will create an instance of A and so on...
The compiler should not allow this since it requires infinite memory.
To solve this, either A or B must use a reference/pointer to the other class.