4

我正在使用具有如下声明的 3rd 方库:

typedef struct {} __INTERNAL_DATA, *HandleType;

我想创建一个在构造函数中采用HandleType的类:

class Foo
{
    Foo(HandleType h);
}

包括定义HandleType的标头。通常,我只是前向声明这种类型,但我无法弄清楚它的语法。我真的很想说:

struct *HandleType;

但这在 GCC 中表示“* 之前的预期标识符”。我能看到的唯一解决方案是像这样编写我的类:

struct __INTERNAL_DATA;
class Foo
{
    Foo(__INTERNAL_DATA *h);
}

但这依赖于库的内部细节。也就是说,它使用名称__INTERNAL_DATA,这是一个实现细节。

似乎应该可以在不使用 __INTERNAL_DATA (库实现的一部分)的情况下前向声明 HandleType (公共 API 的一部分)。有人知道怎么做吗?

编辑:添加了有关我正在寻找的内容的更多详细信息。

4

5 回答 5

4

更新:

我在 Foo 的实现 .cpp 中使用它,但我想避免将它包含在 Foo 的标头 .h 中。也许我只是太迂腐了?:)

是的,你是:) 继续向前声明。

如果 HandleType 是接口的一部分,则必须有一个标头声明它。使用该标题。

你的问题仍然是一个模糊的问题。你正试图保护你做不到的事情。

您可以将以下行添加到客户端库中:

typedef struct INTERNAL_DATA *HandleType;

但是,如果名称/结构发生变化,您可能会遇到一些铸造问题。

尝试模板:

template <class T>
class Foo
{
    Foo(T h);
};

前向声明很好。如果您打算使用指针或引用,您只需要__INTERNAL_DATA在作用域中声明一个类 ( )。但是,如果您要使用成员函数或对象,则需要包含标头。

于 2009-03-10T19:46:53.440 回答
1
 typedef struct {} __INTERNAL_DATA, *HandleType;

如果它是这样定义的(都在一行上),那么 __INTERNAL DATA 与 HandleType 一样是公共接口的一部分。

但是,我认为__INTERNAL_DATA实际上并不存在。很可能,HandleType 实际上(内部)是一个 int。这个奇怪的定义只是一种定义它的方式,它与 int 大小相同,但不同,因此如果您尝试在应该传递 HandleType 的地方传递 int,编译器会给您一个错误。库供应商可以很容易地将其定义为“int”或“void*”,但这样我们就可以进行一些类型检查。

因此__INTERNAL_DATA,这只是一个约定,不会改变。


更新:上面有点打嗝......好吧,__INTERNAL_DATA绝对不存在。我们知道这是一个事实,因为我们可以它的定义视为一个空结构。我猜第 3 方库使用“C”外部链接(没有名称管理),在这种情况下,只需复制 typedef - 就可以了。

在库本身内部,HandleType有完全不同的定义;也许int,也许是“struct MyStruct {.......} *”。

于 2009-03-10T20:05:26.000 回答
1

如果该类型在第 3 方库中,那么前向声明的巨大好处(由于标头的更改而隔离重建)实际上会丢失。

如果您担心编译时间(它是一个相当大的头文件),那么也许您可以将它放在预编译头文件中,或者只包含库中的相关头文件。

例如,许多库标题看起来像

// library.h
#include "Library/Something.h"
#include "Library/SomethingElse.h"
于 2009-03-10T20:09:22.167 回答
1

我不太确定您要做什么,但是以下内容将在不包括实际头文件的情况下起作用:

// foo.h
class Foo
{
    public:
    template<typename T>Foo(T* h) { /* body of constructor */ }
};

请注意,您仍然必须访问__INTERNAL_DATA构造函数体内的公共成员。

编辑:正如 James Curran 所指出的,该__INTERNAL_DATA结构没有成员,因此可以使用它,如上所述,没有问题。

于 2009-03-10T20:16:16.630 回答
1

如果您真的,真的,真的不想将 _INTERNAL_DATA 暴露给调用者,那么您唯一真正的选择是使用typedef void* HandleType;然后在您的库中,您可以做任何您想做的事情,包括更改 *HandleType 的整个实现。

只需创建一个辅助函数来访问您的真实数据。

inline _INTERNAL_DATA* Impl(HandleType h) {
    return static_cast<_INTERNAL_DATA*>(h);
}
于 2009-03-10T20:20:50.847 回答