質問

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

typedef struct {} __INTERNAL_DATA, *HandleType;

そして、コンストラクタで HandleType をとるクラスを作成したいと思います:

class Foo
{
    Foo(HandleType h);
}
HandleType を定義するヘッダーを含む

without 。通常、このような型を前方宣言するだけですが、この構文はわかりません。私は本当に次のようなことを言いたいです:

struct *HandleType;

ただし、「*の前に識別子が必要です」と表示されますGCCで。私が見ることができる唯一の解決策は、私のクラスを次のように書くことです:

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

ただし、これはライブラリの内部詳細に依存しています。つまり、__ INTERNAL_DATAという名前を使用します。これは実装の詳細です。

__ INTERNAL_DATA(ライブラリの実装の一部)を使用せずに、HandleType(パブリックAPIの一部)を前方宣言することが可能であるように思われます。

編集:探しているものの詳細を追加しました。

役に立ちましたか?

解決

更新:

  

Fooの実装.cppで使用していますが、Fooのヘッダー.hに含めることは避けたいです。たぶん私はあまりにもtoo慢になっているのでしょうか? :)

はい、そうです:)前方宣言を進めます。

HandleTypeがインターフェイスの一部である場合、それを宣言するヘッダーが必要です。そのヘッダーを使用します。

あなたの問題はまだあいまいです。できないものから保護しようとしています。

クライアントライブラリに次の行を追加できます。

typedef struct INTERNAL_DATA *HandleType;

ただし、名前/構造が変更された場合は、キャストの意地悪に陥る可能性があります。

テンプレートを試してください:

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

前方宣言は問題ありません。ポインターまたは参照を使用する場合は、スコープ内でクラス( __ INTERNAL_DATA )宣言のみが必要です。ただし、メンバー関数またはオブジェクトを使用する場合は、ヘッダーを含める必要があります。

他のヒント

型がサードパーティのライブラリにある場合、前方宣言(ヘッダーの変更による再構築の分離)の大きな利点は事実上失われます。

コンパイル時間を心配している場合(かなり大きなヘッダーです)、プリコンパイル済みヘッダーに配置するか、ライブラリの関連ヘッダーを含めることができます。

E.g。多くのライブラリヘッダーは次のようになります

// library.h
#include "Library/Something.h"
#include "Library/SomethingElse.h"
 typedef struct {} __INTERNAL_DATA, *HandleType;

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

しかし、 __ INTERNAL_DATA が実際に存在するとは思わない。おそらく、HandleTypeは実際には(内部的に)intです。この奇妙な定義は、intと同じサイズになるように定義する方法ですが、HandleTypeを渡すことになっている場所でintを渡そうとするとコンパイラーがエラーを出すようにします。ライブラリベンダーは、「int」と簡単に定義できます。または&quot; void *&quot;ですが、この方法で何らかの型チェックが行われます。

したがって、 __ INTERNAL_DATA は単なる慣習であり、変更されることはありません。


UPDATE:上記は少し精神的なげっぷでした... OK、 __ INTERNAL_DATA は間違いなく存在しません。空の構造体としての定義を見ることができるため、事実としてこれを知っています。サードパーティのライブラリは&quot; C&quot;を使用していると思います。外部リンケージ(名前の管理なし)。この場合、 typedefをコピーするだけです。問題ありません。

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

_INTERNAL_DATAを呼び出し元に公開したくない場合は、 typedef void * HandleType を使用するしかありません。次に、ライブラリ内で、* HandleTypeの実装全体を変更するなど、必要な操作を実行できます。

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

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

あなたが何をしようとしているのかよくわかりませんが、実際のヘッダーファイルを含めなくても以下は動作します:

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

覚えておいてください、コンストラクタの本体内で __ INTERNAL_DATA のパブリックメンバーにアクセスする必要があります。

編集: James Curranが指摘したように、 __ INTERNAL_DATA 構造体にはメンバーがないため、上記のように問題なく使用できます。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top