未命名结构的前向声明
赏金问题:因此,这两个 Foo
不是同一件事。美好的。第二种形式是在图书馆中提供的。 如果我无法更改它,我如何前向声明它?
我一直认为 C 和 C++ 允许重复声明,前提是没有重复定义。然后我在尝试编写扩展 C 库的 C++ 代码时遇到了这个问题。
struct Foo;
typedef struct {} Foo;
这会产生以下错误:
“struct Foo”之前有一个声明为“struct Foo”
我想转发声明,该死!这是怎么回事?
Bounty question: So, these two Foo
s aren't the same thing. Fine. The second form is given in a library. How do I forward-declare it given that I can't change it?
I always thought C and C++ allowed repeated declarations provided that there were no repeated definitions. Then I came across this problem when trying to write C++ code which extends a C library.
struct Foo;
typedef struct {} Foo;
This gives the following error:
'struct Foo' has a previous declaration as 'struct Foo'
I want to forward-declare, darn it! What's wrong here?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(12)
您的前向声明声明将有一个名为
Foo
的struct
。您的第二个声明是名为
Foo
的typedef
。这些不是同一件事。Your forward declaration declares that there will be a
struct
calledFoo
.Your second declaration is of a
typedef
calledFoo
. These are not the same thing.对于 typedef 的前向声明,您需要引用正在 typedef 的事物,例如:
由于您想要前向声明一个匿名结构,因此您既不能在原始实体的前向声明中给它一个名称,也不能给它一个名称。你可以在定义它时参考它。 “逻辑”语法是:
但由于这显然是不可能的,因此您不能转发声明匿名结构。
为了标准化,让我们看一下 9.1-2:
没有标识符,没有前向声明。
底线是:避免使用匿名结构,除非它们给你带来了你真正需要的优势。
For a forward declaration of a typedef, you need to refer to the thing that is being typedeffed, so like:
Since you want to forward declare an anonymous struct, you can neither give it a name in the forward declaration of the original entity, nor can you refer to it when typedefing it. The "logical" syntax would be:
But since this is obviously not possible, you can not forward declare anonymous structs.
To go standardese, lets have a look at 9.1-2:
No identifier, no forward declaration.
Bottom line of this: avoid anonymous structs unless they give you an advantage that you really need.
您的特定编译器可能会有所不同。
使用 MinGW GCC 3.4.5,两个声明都可以编译,没有错误或警告(使用
-Wall
),并且
库中是否可能已存在前向声明?例如,允许循环指针:
如果库标头中已存在循环指针,则会导致您描述的错误。
Your specific compiler may make a difference here.
Using MinGW GCC 3.4.5, both declarations compile with no errors or warnings (using
-Wall
)and
Is it possible a forward-declaration already exists inside the library? For instance, to allow a circular pointer:
If this already exists within the library headers, it would cause the error you describe.
恕我直言,只需将您的
typedef
更改为,没有任何害处,并且它仍然在 C 和 C 语言中兼容。 C++。现在您可以转发声明了。
[注意:如果您仍然坚持根本不接触
typedef
,那么这里是一个肮脏的伎俩。仅当
Foo.h
仅包含 1 个struct
声明时,此方法才有效。我不推荐它。]IMHO, simply change your
typedef
to,There is no harm and it will still compatible in both C & C++. Now you can forward declare it.
[Note: If you still insist on on not touching the
typedef
at all then here is the dirty trick.This will work, only if
Foo.h
contains only 1struct
declaration. I don't recommend it.]我想我最近遇到了与原始海报相同的问题,并已解决如下:
我正在围绕第三方提供的 API 编写一个包装器,定义为:
Foo.h:
我的包装器需要将 Foo 作为成员,但我不想将 Foo 暴露给我的包装器的所有消费者。
UberFoo.h:
UberFoo.cpp:
现在,我的类的使用者可以实例化它,而无需访问 _foo/Foo 的实际定义。如果我需要将指针作为参数传递给 _foo 或从函数返回它们以及拥有成员 _foo,这也将起作用。
main.cpp:
这里的技巧是转发声明实际的结构类型,而不是 typedef 的名称。请注意,结构不能是匿名的,这一点很重要,这在旧的 C 代码中很常见:
希望这会有所帮助!
I think I recently ran into the same problem as the original poster, and have resolved it as below:
I am writing a wrapper around a third-party provided API defined as:
Foo.h:
My wrapper needs to have Foo as a member, but I don't want to expose Foo to all consumers of my wrapper.
UberFoo.h:
UberFoo.cpp:
Now, the consumers of my class can instantiate it without having access to the actual definition of _foo/Foo. This would also work if I needed to pass pointers to _foo as parameters or return them from functions as well as having a member _foo.
main.cpp:
The trick here was to forward declare the actual struct type, not the typedef'd name. Note that it is critical that the struct not be anonymous, as is common in older C code:
Hope this helps!
您无法转发声明它,因为它未命名。它是一个未命名的结构,其中 Foo 是一个 typedef。
You can't forward declare it, since its unnamed. Its an unnamed struct, for which Foo is a typedef.
你为什么不直接避免前向减速呢?
如果第二个定义位于头文件中,则可以首先将头文件包含在 C++ 头文件中。为了让 C++ 将其视为 C 标头,在大多数情况下,用
extern "C" {
和}
包含 #include 就足够了。Why don't you just avoid forward decl.
If the second definition was in a header file, you could include the header file first in your C++ header file. To make C++ think it as C header, embracing #include with
extern "C" {
and}
must be suffice in most case.您正在尝试输入以前使用过的名称。该声明完全有效,只是您需要使用不同的名称。
请注意,typedef 不能以相同的名称使用。
You are trying to typedef a previously used name. The statement is perfectly valid, only you need to use a different name.
Note that the typedef cannot be used in the same name.
typedef-ing 匿名结构是 C++03 之前的一种做法,主要是为了保持与 C99 之前的编译器的兼容性。
鉴于现在是 2011 年,并且 C++ 和 C 都发生了变化,我想知道为什么这样的库没有更新版本!
如果它不再处于开发阶段,你就不能“离开”,而只能“生存”并改变它,这就是做到这一点的方法。
如果仍在部署中,请将问题提交给开发团队。
如果您需要解决方法,请考虑结构可以继承。
因此,编写一个前向声明
,并将其定义为
在所有代码中,忘记
Foo
并始终使用MyFoo
。typedef-ing anonymous struct is a practice that pre-dates C++03 and is mainly oriented to retain compatibility with pre-C99 compilers.
Given that this is 2011, and that both C++ and C are changed, I wonder why there is no more up-to-date version of such a library!
If it is not in development anymore, you cannot "leave", but just "survive" and change it is the way to do that.
If still in deployment, submit the issue to the development team.
If you need a workaround, consider that struct can inherit.
So, write a forward declaration like
and define it as
And in all your code, forget about
Foo
and always useMyFoo
.您正在声明两个具有相同名称的不同实体。第一个是
struct Foo
,是一个名为Foo
的结构。第二个是匿名结构的别名。如果您这样做:
它可以工作,因为您在这两种情况下都声明了一个名为
Foo
的结构。您不能转发声明匿名结构。您有两个选择:包含整个定义,或者更改标头并命名结构。
You're declaring two different entities with the same name. The first,
struct Foo
, is a struct namedFoo
. The second is an alias for an anonymous struct.If you do instead:
It works, because you're declaring a struct named
Foo
in both situations.You cannot forward declare anonymous structs. You're left with two choices: include the whole definition, or change the header and name the struct.
在类似的情况下,我有一个遗留的 C 头文件,就像
我在自己的 C++ 类中使用它一样,作为私有方法的参数:
为了避免 C.hpp 中的 #include“old_library.h”,我使用以下内容前向声明:
在 C.cpp 中我有以下声明:
这样,我透明地使用 C::Foo 而不是 Foo,并且不需要 MyFoo!
In a similar situation, I have a legacy C header with something like
I use it in a C++ class of my own, as parameter for a private method:
To avoid #include "old_library.h" from C.hpp, I use the following forward declaration:
and in C.cpp I have the following statements:
This way, I use C::Foo instead of Foo transparently, and don't need a MyFoo!
您不需要在 C++ 中键入定义结构:
如果您只想调用它
Foo
而不是 C 中的struct Foo
,您确实需要typedef,也可以通过不同的方式完成:或者
您当然可以在 C 和 C++ 中使用
struct Foo
形式。You don't need to typedef structs in C++:
If you want to call it just
Foo
instead ofstruct Foo
in C, you do need the typedef, which can also be done in different ways:or
You can of course use the form
struct Foo
in both C and C++.