在C ++中转发声明指向结构的结构

时间:2009-03-10 19:42:23

标签: c++ struct forward-declaration

我正在使用第三方库,其声明如下:

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的一部分)。任何人都知道如何?

编辑:添加了有关我正在寻找的更多细节。

5 个答案:

答案 0 :(得分:4)

<强>更新

  

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

是的你是:)继续前进宣言。

如果HandleType是界面的一部分,那么必须有一个标题声明。使用该标题。

你的问题仍然很模糊。你正试图防止你不能做的事情。

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

typedef struct INTERNAL_DATA *HandleType;

但是,如果名称/结构发生变化,您可能会遇到一些拙劣的行为。

尝试模板:

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

前瞻声明没问题。如果要使用指针或引用,则只需要在范围内使用类(__INTERNAL_DATA)声明。但是,如果您要使用成员函数或对象,则需要包含标题。

答案 1 :(得分:1)

 typedef struct {} __INTERNAL_DATA, *HandleType;

如果它被定义为(全部在一行上),则__INTERNAL DATA与HandleType一样是公共接口的一部分。

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

因此__INTERNAL_DATA只是一种惯例而且不会改变。


更新:以上是一个精神打击...好吧,__INTERNAL_DATA肯定不存在。我们知道这是事实,因为我们可以它的定义看作一个空结构。我猜测第三方库使用“C”外部链接(没有名称管理),在这种情况下,只是复制typedef - 它会没问题。

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

答案 2 :(得分:1)

如果类型在第三方库中,则前向声明(由于标题更改而隔离重建)的巨大好处实际上已丢失。

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

E.g。许多库标题看起来像

// library.h
#include "Library/Something.h"
#include "Library/SomethingElse.h"

答案 3 :(得分:1)

我不太确定你的目的是什么,但以下内容可以在不包含实际头文件的情况下运行:

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

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

编辑:正如James Curran所指出的那样,__INTERNAL_DATA结构没有成员,所以如上所述,它可以毫无问题地使用。

答案 4 :(得分:1)

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

只需创建一个辅助函数即可访问您的实际数据。

inline _INTERNAL_DATA* Impl(HandleType h) {
    return static_cast<_INTERNAL_DATA*>(h);
}