31

次のようなクラスを作成すると:

// B.h
#ifndef _B_H_
#define _B_H_

class B
{
private:
    int x;
    int y;
};

#endif // _B_H_

次のように使用します。

// main.cpp
#include <iostream>
#include <vector>

class B; // Forward declaration.

class A
{
public:
    A() {
        std::cout << v.size() << std::endl;
    }

private:
    std::vector<B> v;
};

int main()
{
    A a;
}

コンパイル時にコンパイラが失敗しmain.cppます。今私が知っている解決策は#include "B.h"ですが、なぜ失敗するのか興味があります。g++またはのどちらclのエラー メッセージも、この問題に関しては非常に啓発的ではありませんでした。

4

8 に答える 8

32

実際、A のコンストラクターが B の型を認識しているコンパイル ユニットに実装されている場合、この例はビルドされます。

std::vector インスタンスは、他の人が前に言ったように、T へのポインターのみを含むため、T が何であっても固定サイズを持ちます。しかし、ベクトルのコンストラクターは具象型に依存します。A() がベクトルの ctor を呼び出そうとするため、この例はコンパイルされません。これは、B を知らずに生成することはできません。

Aの宣言:

// A.h
#include <vector>

class B; // Forward declaration.

class A
{
public:
    A(); // only declare, don't implement here

private:
    std::vector<B> v;
};

Aの実装:

// A.cpp
#include "A.h"
#include "B.h"

A::A() // this implicitly calls vector<B>'s constructor
{
    std::cout << v.size() << std::endl;
}

A のユーザーは、B ではなく A のみを知る必要があります。

// main.cpp
#include "A.h"

int main()
{
    A a; // compiles OK
}
于 2013-03-13T10:29:06.843 に答える
31

コンパイラは、適切なレイアウト情報を生成する前に、「B」の大きさを知る必要があります。代わりに、あなたが言っstd::vector<B*>た場合、コンパイラはポインターの大きさを知っているので、B の大きさを知る必要はありません。

于 2008-09-01T01:29:43.617 に答える
5

A::v をインスタンス化するには、コンパイラは B の具体的な型を知る必要があります。

コンパイル時間を改善するために #include されるバゲージの量を最小限に抑えようとしている場合、できることが 2 つあります。

  1. B へのポインターを使用する
  2. B への軽量プロキシを使用する
于 2008-09-01T01:29:36.940 に答える
3

必要なのはBのサイズだけではありません。最近のコンパイラには、たとえば、可能な場合はmemcpyを使用してベクトルコピーを高速化するための巧妙なトリックがあります。これは通常、要素タイプのPOD性に部分的に特化することで実現されます。Bが前方宣言からPODであるかどうかはわかりません。

于 2008-09-26T12:19:08.393 に答える
1

これは、ベクトルを使用するか、1つのBをインスタンス化しようとするかは関係ありません。インスタンス化には、オブジェクトの完全な定義が必要です。

于 2008-09-26T12:53:35.223 に答える
0

男、あなたはstd::vector不完全な型でインスタンス化しています。前方宣言には触れないでください。コンストラクターの定義を.cppファイルに移動するだけです。

于 2012-12-23T12:19:41.570 に答える
-12

前方宣言を使用できない理由は、 B のサイズが不明であるためです。

あなたの例では、Ah の中に Bh を含めることができないという理由はありません。では、実際に解決しようとしている問題は何ですか?

編集:この問題を解決する別の方法もあります: C/C++ の使用をやめる! それはとても1970年代です... ;)

于 2008-09-01T01:30:10.697 に答える