如何创建 typedef 结构的前向声明
how to create a forward declaration of a typedef struct
我有 1 个 .h 文件 test.h
,其中包含一个 class。在这个 class 中有一个私有方法 return 在我不想创建 "public" 的类型上设置一个指针,但我希望能够包含这个 test.h
文件在其他源文件中。
一般来说,在.h文件中使用前向声明很容易:
class Foo;
但问题是这个类型来自一个 C 文件我不能改变(因为它是我不维护的其他人的代码)而且它是一个typedef
.
基本上我的 test.cpp
是:
// this type comes from a C file, cannot be changed to struct or class
typedef struct
{
int x;
} Foo;
#include "test.h"
static Foo foo;
Foo *Test::private_function()
{
foo.x = 12;
return &foo;
}
int Test::compute()
{
auto *local_foo = private_function();
return local_foo->x;
}
我的 test.h
文件是:
#pragma once
struct Foo;
class Test
{
public:
Test() {}
int compute();
private:
Foo *private_function();
};
尝试编译失败:
>g++ -std=c++11 -c test.cpp
In file included from test.cpp:10:0:
test.h:3:8: error: using typedef-name 'Foo' after 'struct'
test.cpp:7:3: note: 'Foo' has a previous declaration here
目前我的解决方法是 return void *
来回执行 static_cast
,但我认为这不是最佳选择。有更好的解决方案吗?
(我检查了 Forward declaration of a typedef in C++ 但我测试了解决方案,它们似乎对我的情况不起作用,也许我想做的是 simpler/different - 我只有一个 .h和 .cpp - 或者根本不可能)
Return这个:
//#include "SecretFoo.h"
struct SecretFoo {
uintptr_t handle;
};
//#include "SecretFooImpl.h"
#include "SecretFoo.h"
#include "Foo.h" // definition of typedef struct {int x;} Foo;
Foo* Crack( SecretFoo foo ) {
return reinterpret_cast<Foo*>(foo.handle);
}
SecretFoo Encase( Foo* foo ) {
return {reinterpret_cast<uintptr_t>(foo)};
}
现在我们得到:
#include "SecretFooImpl.h"
static Foo foo;
SecretFoo Test::private_function()
{
foo.x = 12;
return Encase(&foo);
}
int Test::compute()
{
auto *local_foo = Crack(private_function());
return local_foo->x;
}
在你的 header:
#pragma once
#include "SecretFoo.h"
class Test
{
public:
Test() {}
int compute();
private:
SecretFoo private_function();
};
这归结为相同的二进制代码,但是 SecretFoo
和成对的 Crack
/Encase
函数提供了一种比 void*
更安全的转换。
这种技术有时在 C 世界中使用。 SecretFoo
是句柄的一种;不透明的 pointer-like 结构。其中的数据(uintptr_t handle
)在本例中只是一个强制转换指针;但它可能是指向 table 指针或其他任何东西的指针。 Crack
和 Encase
方法是 access/create SecretFoo
.
唯一允许的方法
不幸的是,typedef 不能前向声明。
一个常见的解决方法是让 C++ class 继承自 C 结构,由其 typedef 引用,并且您可以前向声明它。这将需要一些代码更改,但它们应该是最小的。
(代表 https://whosebug.com/users/3943312/sam-varshavchik 评论者发帖)
我有 1 个 .h 文件 test.h
,其中包含一个 class。在这个 class 中有一个私有方法 return 在我不想创建 "public" 的类型上设置一个指针,但我希望能够包含这个 test.h
文件在其他源文件中。
一般来说,在.h文件中使用前向声明很容易:
class Foo;
但问题是这个类型来自一个 C 文件我不能改变(因为它是我不维护的其他人的代码)而且它是一个typedef
.
基本上我的 test.cpp
是:
// this type comes from a C file, cannot be changed to struct or class
typedef struct
{
int x;
} Foo;
#include "test.h"
static Foo foo;
Foo *Test::private_function()
{
foo.x = 12;
return &foo;
}
int Test::compute()
{
auto *local_foo = private_function();
return local_foo->x;
}
我的 test.h
文件是:
#pragma once
struct Foo;
class Test
{
public:
Test() {}
int compute();
private:
Foo *private_function();
};
尝试编译失败:
>g++ -std=c++11 -c test.cpp
In file included from test.cpp:10:0:
test.h:3:8: error: using typedef-name 'Foo' after 'struct'
test.cpp:7:3: note: 'Foo' has a previous declaration here
目前我的解决方法是 return void *
来回执行 static_cast
,但我认为这不是最佳选择。有更好的解决方案吗?
(我检查了 Forward declaration of a typedef in C++ 但我测试了解决方案,它们似乎对我的情况不起作用,也许我想做的是 simpler/different - 我只有一个 .h和 .cpp - 或者根本不可能)
Return这个:
//#include "SecretFoo.h"
struct SecretFoo {
uintptr_t handle;
};
//#include "SecretFooImpl.h"
#include "SecretFoo.h"
#include "Foo.h" // definition of typedef struct {int x;} Foo;
Foo* Crack( SecretFoo foo ) {
return reinterpret_cast<Foo*>(foo.handle);
}
SecretFoo Encase( Foo* foo ) {
return {reinterpret_cast<uintptr_t>(foo)};
}
现在我们得到:
#include "SecretFooImpl.h"
static Foo foo;
SecretFoo Test::private_function()
{
foo.x = 12;
return Encase(&foo);
}
int Test::compute()
{
auto *local_foo = Crack(private_function());
return local_foo->x;
}
在你的 header:
#pragma once
#include "SecretFoo.h"
class Test
{
public:
Test() {}
int compute();
private:
SecretFoo private_function();
};
这归结为相同的二进制代码,但是 SecretFoo
和成对的 Crack
/Encase
函数提供了一种比 void*
更安全的转换。
这种技术有时在 C 世界中使用。 SecretFoo
是句柄的一种;不透明的 pointer-like 结构。其中的数据(uintptr_t handle
)在本例中只是一个强制转换指针;但它可能是指向 table 指针或其他任何东西的指针。 Crack
和 Encase
方法是 access/create SecretFoo
.
不幸的是,typedef 不能前向声明。
一个常见的解决方法是让 C++ class 继承自 C 结构,由其 typedef 引用,并且您可以前向声明它。这将需要一些代码更改,但它们应该是最小的。
(代表 https://whosebug.com/users/3943312/sam-varshavchik 评论者发帖)