未命名结构的前向声明
Forward declarations of unnamed struct
赏金问题:所以,这两个Foo
不是一回事。很好。第二种形式是在图书馆给出的。如果我不能更改它,我如何向前声明它?
我一直认为C和c++允许重复声明,只要没有重复的定义。然后我在尝试编写扩展C库的c++代码时遇到了这个问题。
struct Foo;
typedef struct {} Foo;
这会产生以下错误:
'struct Foo'前面有一个声明为'struct Foo'
我想向前声明,该死!这是怎么了?
类型定义匿名结构是c++ 03之前的一种实践,主要是为了保持与c99之前的编译器的兼容性。
考虑到这是2011年,c++和C都改变了,我想知道为什么没有这样一个库的最新版本!
如果它不再处于发展中,你不能"离开",只能"生存",改变它是做到这一点的方法。如果仍在部署中,请将问题提交给开发团队。
如果需要变通,考虑该结构可以继承。因此,写一个像
这样的前向声明struct MyFoo;
并定义为
#include "old_library.h"
struct MyFoo: public Foo {};
在你所有的代码中,忘记Foo
而总是使用MyFoo
.
你声明了两个具有相同名称的不同实体。第一个是struct Foo
,是一个名为Foo
的结构体。第二个是匿名结构的别名。
如果你这样做:
struct Foo;
struct Foo {};
它可以工作,因为在这两种情况下你都声明了一个名为Foo
的结构体。
不能转发声明匿名结构。您有两种选择:包括整个定义,或者更改头文件并命名结构体。
在类似的情况下,我有一个类似
的旧C头文件== old_library.h ==
typedef struct { int data; } Foo;
== /old_library.h ==
我在自己的c++类中使用它,作为私有方法的参数:
class C {
void run(Foo *ds);
...
}
为了避免C.hpp中的#include "old_library.h",我使用了以下前向声明:
class C {
struct Foo;
void run(Foo *ds);
...
}
和C.cpp中有以下语句:
extern "C" {
#include "old_library.h"
}
struct C::Foo : public ::Foo {};
这样,我透明地使用C::Foo而不是Foo,并且不需要MyFoo!
你不需要在c++中定义类型:
struct Foo; // Forward declaration
struct Foo
{
}; // Definition
如果您想在C中只调用Foo
而不是struct Foo
,则需要类型定义,这也可以通过不同的方式完成:
struct Foo; /* Forward declaration */
struct Foo /* The name is needed here */
{
}; /* Definition */
typedef struct Foo Foo; /* typedef */
或
struct Foo; /* Forward declaration */
typedef struct Foo /* The name is needed here */
{
} Foo; /* Definition and typedef combined */
当然可以在C和c++中使用struct Foo
的形式。
您的forward声明声明将有一个struct
称为Foo
。
第二个声明是typedef
,称为Foo
。这不是一回事。
对于类型定义的前向声明,您需要引用正在被类型定义的内容,例如:
struct foo;
typedef foo bar;
class foo{};
因为你想要前向声明一个匿名结构,你既不能在原始实体的前向声明中给它一个名字,也不能在对它进行类型定义时引用它。"逻辑"语法应该是:
struct ;
typedef bar;
class {};
但是由于这显然是不可能的,所以你不能向前声明匿名结构。
让我们看一下9.1-2:
仅由类键标识符组成的声明;要么是在当前作用域或forward中重新声明名称将标识符声明为类名。它介绍了这个类
没有标识符,没有前向声明。
底线:避免匿名结构,除非它们给你真正需要的优势。
您的特定编译器在这里可能会有所不同。
使用MinGW GCC 3.4.5,两个声明编译时没有错误或警告(使用-Wall
)
struct Foo;
typedef struct {} Foo;
和
struct Foo;
typedef struct Foo {} Foo;
是否可能在库中已经存在前向声明?例如,要允许一个循环指针:
struct Foo;
typedef struct Foo {
struct Foo *fooPtr;
} Foo;
如果这已经存在于库头文件中,它将导致您所描述的错误。
IMHO,只需将typedef
更改为,
typedef struct Foo {} Foo;
^^^^^
这是没有害处的,它仍然在C &c++。现在你可以向前声明了。
[注:如果你仍然坚持不碰typedef
,那么这里是肮脏的技巧。
struct Foo;
#define struct struct Foo
#include"Foo.h" // contains typedef struct {} Foo;
#undef struct
这将工作,只有当Foo.h
只包含一个struct
声明。我不推荐使用
我想我最近遇到了与原来海报相同的问题,并已解决如下:
我正在编写一个围绕第三方提供的API的包装器,定义为:
foo:
typedef struct _foo
{
int i;
} Foo;
Foo* MakeFoo();
int UseFoo(Foo* foo);
我的包装器需要将Foo作为成员,但我不想将Foo暴露给包装器的所有消费者。
UberFoo.h:
#pragma once
struct _foo; // forward declare the actual type _foo, not the typedef Foo
class UberFoo
{
public:
UberFoo();
int GetAnswer();
private:
_foo* f;
};
UberFoo.cpp:
#include "UberFoo.h"
#include "Foo.h"
UberFoo::UberFoo()
{
this->f = MakeFoo();
}
int UberFoo::GetAnswer()
{
return UseFoo(f);
}
现在,我的类的消费者可以实例化它,而不必访问_foo/Foo的实际定义。如果我需要将指针作为参数传递给_foo或从函数返回指针,以及拥有成员_foo,这也可以工作。
main.cpp:
#include <cstdio>
#include "UberFoo.h"
int main(int argc, char* argv[])
{
UberFoo u;
printf( "The Answer = %dn", u.GetAnswer());
return 0;
}
这里的技巧是转发声明实际的结构类型,而不是类型定义的名称。请注意,结构体不能是匿名的,这一点很重要,因为在旧的C代码中很常见:
typedef struct // the actual struct type underlying the typedef is anonymous here
{
int i;
} ThisWontWork;
希望这对你有帮助!
你不能向前声明它,因为它是未命名的。它是一个未命名的结构体,Foo是一个类型定义。
为什么不直接避免转发呢?
如果第二个定义在头文件中,可以首先在c++头文件中包含这个头文件。为了使c++将其视为C头文件,在大多数情况下,在extern "C" {
和}
中包含#include就足够了。
您正在尝试定义以前使用过的名称。该语句完全有效,只是需要使用不同的名称。
struct Foo; // Forward declaration of struct Foo
typedef struct {} anotherFoo; // Another structure typedefed
struct Foo {
// Variables
}; // Definition of the forward declared Foo.
- 在哪里声明结构运算符重载
- 如何正确转发声明结构"using XXX"?
- 在C++我可以在不在本地声明结构的情况下将结构作为指针传递吗?
- 在 for 循环中声明结构是否合法C++?
- 为什么我们可以创建一个模板类结构,其中包含许多与声明结构时指定的参数不同的参数
- 当声明结构数组时,CPPCHECK停止对整个文件的分析
- C++ - 声明结构和类时不允许使用不完整的类型
- 在声明末尾或 main 中声明结构或类实例之间的区别
- 在模板类中声明结构,未为成员函数定义
- C++ .h 文件中转发声明结构,并在.cpp文件中定义结构
- 如何在C++中声明结构变量
- 在 C 中声明结构的新实例
- 在类内部声明结构
- 为什么可以用相同的名称声明结构和非结构
- 在结构定义内部声明结构的堆栈
- 为什么在声明结构时不能初始化结构中的向量成员?
- 在c++头文件中声明结构体
- 如何声明结构体?
- c++中声明结构体的问题
- 只在库cpp中有定义的前向声明结构