2010-12-02 19 views
10

関数の前方宣言がソースファイル(.cpp)で機能するとき、なぜ同じことがクラスに対して機能しないのでしょうか?クラスの前方宣言、関数

ありがとうございました。

// main.cpp 

void forwardDeclaredFunction() ; // This is correct 

class One ; // Why this would be wrong 

int One:: statVar = 10 ; 

void 
One :: anyAccess() { 

std::cout << "\n statVar:\t " << statVar ; 
std::cout << "\n classVar:\t" << classVar ; 
} 

class One { 

public: 
    void anyAccess() ; 
    static int statVar ; 

private: 
    int classVar ; 

} ; 


int main (int argc, char * const argv[]) { 

One *obj = new One ; 

     return 0; 
} 

void forwardDeclaredFunction() { 
} 
+3

'class One;'は、フォワードクラス宣言の正しい構文です。どんなコンパイラエラーメッセージが表示されていますか? –

+1

エラー:不完全なタイプの構造体1の無効な使用。私はMac – Mahesh

答えて

11

前方宣言があまりにもクラスのために働くことができます:の実際の定義

class Foo; 

class Bar { 
public: 
    Foo *myFoo; // This has to be a pointer, thanks for catching this! 
}; 

class Foo { 
public: 
    int value; 
}; 

上記のコードがfooクラスの前方宣言を示し、他のクラスタイプのFoo *の変数を使用して(バー) Fooクラス。 C++では、コードを使用する前に実装していない限り、実装されていないものを残すかどうかは気にしません。特定の型のオブジェクトへのポインタを定義することは、そのコードを使用することではありません。

すばやく、汚い返信ですが、それが助けてくれることを願っています。

編集:実装されていないクラスのポインタでない変数を宣言すると、記載されている応答としてコンパイルされません。そうすることは、まさに私が「コードを使って」意味することです。この場合、Fooコンストラクタは、Barコンストラクタが呼び出されるたびに呼び出されます。ただし、Foo型のメンバ変数があるとします。コンパイラは、後でFooを実装する予定があることを知らないので、エラーが発生します。私の間違いのために申し訳ありません;)。

+2

AFAIKで動作しています。フォワード宣言では、宣言されたクラスのオブジェクトを持たせることはできません - ポインタのみ、場合によっては参照。あなたの例では、コンパイラは 'sizeof(Foo)'をまだ知ることができず、 'Bar'を定義することができません。 – cHao

+2

これはOPのコードが失敗したのと同じ理由でコンパイルされません。完全構造がわかる前にFooを使用しています(gccは "field 'myFoo'に不完全な型があると伝えます) – Lars

+1

参照を宣言することもできます例えば、 'const Foo&myFoo'のように、それが型宣言されているだけです。 –

3

メンバーの実装の前に、メンバーの宣言を配置します。

class One { 

public: 
    void anyAccess() ; 
    static int statVar ; 

private: 
    int classVar ; 

} ; 

int One:: statVar = 10 ; 

void 
One :: anyAccess() { 

std::cout << "\n statVar:\t " << statVar ; 
std::cout << "\n classVar:\t" << classVar ; 
} 
5

前方宣言class One;はあなたではなく、そのメンバーのいずれかにクラス自体を参照することができます。あなたはクラスの完全な宣言の後にクラスメンバのすべての定義を入れなければなりません。

2

int One:: statVar = 10 ;にエラーメッセージが表示されていますが、これは正式な宣言ではありません。

静的メンバーを定義する前に、コンパイラはクラスの完全な定義を知る必要があります。前方宣言が不十分です(クラス定義から型が正しいことを確認できる必要があります)。

静的属性定義をクラス定義の下に移動する必要があります。

2

コンパイラはstuffを最初から最後まで読み込み、コードを生成します。しかし、クラスが定義される前に、コンパイラはOne::statVarまたはOne::anyAccessが存在するかどうか、あるいはその関数が仮想、静的、または何であるかを知りません。コードを生成するためには、そのことを知る必要があります。

0

あなたは2クラス&一つの関数を作成して別のクラス にクラス上のデータにアクセスすることができ、それは

forword宣言は次の

でどのクラス

クラスABCを知るために使用されるフレンド関数です。

クラスXYZ

{

データ部材と

公開:

friend getdata();

他のメンバ関数

}

クラスABC

{

データメンバ

公共:

友人ボイド函();