1

不完全な型をパラメーターとして取る関数を定義できないことはわかっているため、以下のコードはエラー C2027: use of undefined type 'Derived' でコンパイルに失敗することが予想されます。

class Derived;
class Base{
public:
   void test(Derived d){ cout<<"test"<<endl; }
};
class Derived : public Base{
   int j;
};

同じ論理で、test() がその時点まで不完全な型である Base のオブジェクトを受け取ると、コンパイルが失敗することが予想されます。ただし、そうではなく、次のコードは正常にコンパイルされます

class Derived;
class Base{
public:
    void test(Base b){ cout<<"test"<<endl; }
};
class Derived : public Base{
    int j;
};

クラスが定義されている間に私たちが持っている不完全なクラス型と前方宣言によって公開された不完全な型の間に違いはありますか?

4

1 に答える 1

3

ロジックは同じではありません。違いは、2 番目の例の関数では、(完全に外部の class ではなく)Base::test()独自のクラスのオブジェクトを使用することです。BaseDerived

この言語は、8.3.5/6 (C++03) でこの状況を特別に扱います。

関数定義のパラメーターの型または関数定義の戻り値の型は、関数定義がそのクラスのメンバー仕様内でネストされていない限り、不完全なクラス型 (おそらく cv 修飾) であってはなりません (クラス内で定義されたネストされたクラスの定義を含む)。 )。

このルールは、別の同様のルールの「サテライト」と見なすことができます。このルールは、クラスの型が、クラス メンバー関数の本体、デフォルトの引数、およびコンストラクターの初期化リストから常に全体として (および完全な型として) 見られることを示しています。9.2/2 (C++03) を参照

クラスは、クラス指定子の最後の } で、完全に定義されたオブジェクト型 (3.9) (または完全な型) と見なされます。クラス メンバ仕様内では、クラスは関数本体、デフォルト引数、およびコンストラクタ ctor-initializer (ネストされたクラス内のそのようなものを含む) 内で完全であると見なされます。それ以外の場合は、それ自体のクラス メンバー仕様内では不完全であると見なされます。

クラスを閉じる前の他のすべてのコンテキストでは}、クラスは不完全であると見なされることに注意してください

struct S {
  S foo(S s) // <- OK, due to 8.3.5/6
    { return s; } 

  void bar(int a = sizeof(S)) // <- OK, due to 9.2/2
    { S s; } // <- OK, due to 9.2/2

  int (*baz())[sizeof(S)] // <- ERROR: incomplete type in `sizeof`
    { return NULL; }

  void qux(int a[sizeof(S)]) // <- ERROR: incomplete type in `sizeof`
    {}
};
于 2013-07-11T04:47:17.923 に答える