4

次のような宣言を持つサードパーティのライブラリを使用しています。

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

本当に、本当に、本当に_INTERNAL_DATAを呼び出し元に公開したくない場合、唯一の本当の選択はtypedef void*HandleTypeを使用することです。次に、ライブラリ内で、* HandleTypeの実装全体を変更するなど、必要なことをすべて実行できます。

実際のデータにアクセスするためのヘルパー関数を作成するだけです。

inline _INTERNAL_DATA* Impl(HandleType h) {
    return static_cast<_INTERNAL_DATA*>(h);
}
于 2009-03-10T20:20:50.847 に答える
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
 typedef struct {} __INTERNAL_DATA, *HandleType;

そのように (すべて 1 行で) 定義されている場合、__INTERNAL DATA は、HandleType と同じくらいパブリック インターフェイスの一部です。

__INTERNAL_DATAただし、実際には存在しないと思います。おそらく、HandleType は実際には (内部的に) int です。この奇妙な定義は、int と同じサイズであるが区別できるように定義する方法にすぎないため、HandleType を渡すことになっている場所に int を渡そうとすると、コンパイラはエラーを返します。ライブラリ ベンダーは、"int" または "void*" と同じように簡単に定義できますが、この方法で型チェックを行うことができます。

したがって、これ__INTERNAL_DATAは単なる慣習であり、変わることはありません。


更新: 上記は少し精神的なげっぷでした... OK、__INTERNAL_DATA間違いなく存在しません。空の構造体として定義されていることがわかるので、これは事実としてわかります。サードパーティのライブラリは "C" 外部リンケージ (名前の管理なし) を使用していると推測します。その場合は、typedef をコピーするだけで問題ありません。

ライブラリ自体の内部では、HandleTypeの定義まったく異なります。たぶんint、多分「struct MyStruct {.......} *」。

于 2009-03-10T20:05:26.000 に答える