2009-04-30 16 views

答えて

12

型を宣言するために、そのサイズを知る必要があります。型へのポインタを宣言したり、型へのポインタをtypedefしたりすることができます。

本当にしたい場合は、pimplイディオムを使用してインクルードを下げておくことができます。しかし、ポインタではなくタイプを使用したい場合、コンパイラはそのサイズを知る必要があります。

編集:j_random_hackerはサイズが使用タイプに知ることが必要である基本的にことを、この回答への重要な資格が追加されますが、我々は唯一の存在するタイプを知っておく必要がある場合は前方宣言をして、行うことができますその型へのポインタまたは参照を作成します。 OPはコードを示していないが、コンパイルしないと訴えていたので、私はOPがを使用しようとしていたと仮定しただけではなく、というタイプを使用していました。

+30

まあ、クラス型の前方宣言は、そのサイズの知識がなくても、これらのタイプを宣言します。これを考慮してください。また、ポインタとそのような不完全な型への参照を定義できることに加えて、パラメータを取る、および/またはそのような型の値を返す関数を宣言することはできますが、定義することはできません。 –

+3

申し訳ありませんが、私はそれが良い前提だとは思いません。この回答は、ポイントの横にあります。これは、前方宣言のtypedefの場合と非常によく似ています。 – Cookie

143

正式なtypedefを行うことができます。しかし

typedef A B; 

を行うには、まず、前方Aを宣言しなければなりません:C++(ただし、プレーンC)では

class A; 

typedef A B; 
+8

最終的には+1となります。技術的に "forward-typedef"(つまり "typedef A;"を書くことはできません)では、上記のトリックを使ってOPが達成したいことをほぼ確実に達成できるからです。 –

+8

typedefが変更された場合、すべてのforward宣言も変更される可能性があることに注意してください。古いものと新しいtypedefが同じインタフェースを持つ型を使用すると見逃してしまう可能性があります。 – math

+10

これは楽しいテンプレート化されたクラスでは機能しません。 – Alex

15

を、それはとても長い間、両方の定義が完全にあるとして、二度タイプをtypedefのために完全に合法です同じ:typedeを使用して定義されたCスタイルの構造体を宣言転送するために探している人、私のようなあなたのそれらについては、

// foo.h 
struct A{}; 
typedef A *PA; 

// bar.h 
struct A; // forward declare A 
typedef A *PA; 
void func(PA x); 

// baz.cc 
#include "bar.h" 
#include "foo.h" 
// We've now included the definition for PA twice, but it's ok since they're the same 
... 
A x; 
func(&x); 
+29

メンテナンスいいえいいえ、この種のことは、飼い主の中で遅かれ早かれあなたを噛むでしょう。 –

+1

@MarkStorer、少なくともコンパイラはどんな違いも捕らえてエラーを生成します。私はこれをVisual C++で検証しました。 – Alan

+0

いいですが、 'A'が定義によって空であるので、この方法で' A'フィールドをどのように定義しますか? –

41

fは、いくつかのC++のコードでは、私はあなたがFWDクラスまたは構造体を宣言した後、あなたが宣言された型をtypedefをすることができます必要な「FWDのtypedefを宣言」するには...

// a.h 
typedef struct _bah { 
    int a; 
    int b; 
} bah; 

// b.h 
struct _bah; 
typedef _bah bah; 

class foo { 
    foo(bah * b); 
    foo(bah b); 
    bah * mBah; 
}; 

// b.cpp 
#include "b.h" 
#include "a.h" 

foo::foo(bah * b) { 
    mBah = b; 
} 

foo::foo(bah b) { 
    mBah = &b; 
} 
+1

+1のプラグマティズム – Travis

+0

@LittleJohnこの解決策の問題は、ダミー名_bahがパブリックAPIの一部と見なされないことです。 forward delcare FILEを参照してください。 – user877329

10

を次のようになります解決策を発見しました。複数の同一のtypedefがコンパイラによって受け入れられます。

長い形式:

class MyClass; 
typedef MyClass myclass_t; 

短い形式:あなたは型自体を使用して意図ないをしているときにのみ

typedef class MyClass myclass_t; 
6

前方宣言を使用したフル#include秒の代わりにが可能です(このファイルの有効範囲内)ではなく、ポインタまたはその参照です。

型自体を使用するには、コンパイラはそのサイズを知っている必要があります。そのため、完全な宣言が必要です。したがって、完全な#includeが必要です。

ただし、ポインタまたは参照のサイズは、pointeeのサイズに関係なくコンパイラに認識されます。したがって、前方宣言で十分です。型識別子の名前が宣言されています。classまたはstruct型へのポインタまたは参照を使用している場合

興味深いことに、コンパイラはあなたにも指示先の型を宣言転送する必要性を保存不完全型扱うことができます。

// header.h 

// Look Ma! No forward declarations! 
typedef class A* APtr; // class A is an incomplete type - no fwd. decl. anywhere 
typedef class A& ARef; 

typedef struct B* BPtr; // struct B is an incomplete type - no fwd. decl. anywhere 
typedef struct B& BRef; 

// Using the name without the class/struct specifier requires fwd. decl. the type itself.  
class C;   // fwd. decl. type 
typedef C* CPtr; // no class/struct specifier 
typedef C& CRef; // no class/struct specifier 

struct D;  // fwd. decl. type 
typedef D* DPtr; // no class/struct specifier 
typedef D& DRef; // no class/struct specifier 
1

を私は同じ問題を持っていました、異なるファイル内に複数のtypedefを台無しにしたくなかったので、私は、継承とそれを解決:

されました:

class BurstBoss { 

public: 

    typedef std::pair<Ogre::ParticleSystem*, bool> ParticleSystem; // removed this with... 

ました:

class ParticleSystem : public std::pair<Ogre::ParticleSystem*, bool> 
{ 

public: 

    ParticleSystem(Ogre::ParticleSystem* system, bool enabled) : std::pair<Ogre::ParticleSystem*, bool>(system, enabled) { 
    }; 
}; 

を魅力のように働きました。もちろん、私は

BurstBoss::ParticleSystem 

単に

ParticleSystem 
0

からすべての参照を変更しなければならなかったビルKotsiasが指摘したように、プライベートあなたのポイントのtypedefの詳細を維持し、前方にそれらを宣言するための唯一の合理的な方法であります継承あり。あなたはC++ 11でこれをもっとうまくいくことができます。

// LibraryPublicHeader.h 

class Implementation; 

class Library 
{ 
... 
private: 
    Implementation* impl; 
}; 
// LibraryPrivateImplementation.cpp 

// This annoyingly does not work: 
// 
//  typedef std::shared_ptr<Foo> Implementation; 

// However this does, and is almost as good. 
class Implementation : public std::shared_ptr<Foo> 
{ 
public: 
    // C++11 allows us to easily copy all the constructors. 
    using shared_ptr::shared_ptr; 
};