8

C++ のクイズをやっています。そして、次のコードに出くわしました-違法ですが、理由がわかりません。誰でもこの行の理由を説明できますか:

Box* b1 = s1->duplicate();

「Shape* から Box に変換できません」というコンパイラ エラーが生成されますか? 実際には - を指しているため、それs1->duplicate()が呼び出していると想定しましたが、コンパイラ エラーからは呼び出しているように見えます。Box::duplicate()s1BoxShape::duplicate()

#include <iostream>

struct Shape
{
  virtual Shape* duplicate()
  {
    return new Shape;
  }

  virtual ~Shape() {}
};

struct Box : public Shape
{
  virtual Box* duplicate()
  {
    return new Box;
  }

};

int main(int argc, char** argv) 
{ 
  Shape* s1 = new Box;

  Box* b1 = s1->duplicate();

  delete s1;
  delete b1;
  return 0; 
}
4

3 に答える 3

15

C++ 言語は静的に型付けされます。呼び出しの合法性に関する決定は、コンパイル時に行われます。明らかに、コンパイラは がオブジェクトs1->duplicate()へのポインターを返すことを認識できません。Boxこのような状況では、コードが受け入れられると期待するのは非論理的です。

はい、s1->duplicate()確かBox::duplicateにあなたの例で呼び出しますが、コンパイラーがこれをどのように認識すると思いますか? 特定の例から「明らか」であると言えますが、この言語機能の仕様は、そのような「明白な」ケースを例外としません。

于 2012-08-15T21:17:28.957 に答える
8

Shape::duplicates()Shape*ではない を返しますBox*。実際に返すランタイム型は、それとは何の関係もありません。Shape*コンパイラは、返された が実際に を指していることをどのように知ることができBoxますか?

編集:これについて考えてください:

struct Shape
{
  virtual Shape* duplicate()
  {
    return new Shape;
  }

  virtual ~Shape() {}
};

struct Box : public Shape
{
  virtual Box* duplicate()
  {
    return new Box;
  }

};

struct Sphere : public Shape
{
  virtual Sphere* duplicate()
  {
    return new Sphere;
  }

};

Shape* giveMeABoxOrASpehere()
{
    if ( rand() % 2 )
       return new Box;
    else
       return new Sphere;
}

//
Shape* shape = giveMeABoxOrASphere();
// What does shape->duplicate() return?

Box* shape = giveMeABoxOrASphere();
// shoud this compile?
于 2012-08-15T21:17:53.010 に答える
1

全く同じ理由で

Shape* s1 = new Box;
Box* b1 = s1;

コンパイルしません。コンパイラはs1が a を参照することを気にしませんし、気にBoxする必要もありません。

s1が a を参照していることがわかっている場合は、次のBoxように言ってください。

Box *s1 = new Box;

構文に関する注意: の解析規則Box * s1;は (非常に単純化されています):

declaration := type-name declarator ;
declarator := name 
            | * declarator

したがって、解析は次のとおりです。

   Box        *       s1        ;
                   ^^^^^^^^
                  declarator
^^^^^^^^^    ^^^^^^^^^^^^^^^^^^
type-name         declarator

グループ化はBox (* (s1) )

1 つの宣言で複数の変数を宣言すると、構文が混乱する可能性がありBox *s1;ます。Box* s1;Box*

Box* x, y;

xへのポインタですがBox、解析は次のとおりです。yBox

Box (*x), y;
于 2012-08-16T00:12:16.513 に答える