1

型は階層の最も深い部分に自動的に解決されると思いました。を呼び出し、from クラスをオーバーライドすると、基本クラスで提供される奇妙な一般的な不平ではなく、猫は「ニャー」と言うでしょう。Cat : Animalcat->talk()Cattalk()AnimalAnimalAnimal

だから私はこれについて混乱しています:

struct Animal
{
  virtual void talkTo( Animal* o ) {
    puts( "Animal-Animal" ) ;
  }
} ;

struct Cat : public Animal
{
  virtual void talkTo( Animal* o ) {
    puts( "Cat-Animal" ) ;
  }
  virtual void talkTo( Cat* o ) {
    puts( "Cat says meow to Cat" ) ;
  }
} ;

呼び出しコードは次のとおりです。

  Cat *cat = new Cat() ;
  cat->talkTo( cat ) ; //Cat says meow to Cat

  Animal *animalCatPtr = cat ;      
  cat->talkTo( animalCatPtr ) ; //Cat-Animal

ここの最後の行では、Cattoを送信していますcat->talkToが、 を使用していanimalCatPtrます。 animalCatPtrは引き続き a を参照しますが、関数呼び出しではCat単に an に解決されます。Animal

パス ポインタを実際の階層の最も深い型に解決するにはどうすればよいですか? 私が手元に持っているものが本当にあなたのものかどうかdynamic_cast<>を確認するために一連のテストを行いたくありません。AnimalCatDog

4

2 に答える 2

2

二重発送の形式が必要な場合は、http://en.wikipedia.org/wiki/Double_dispatchを参照してください。

于 2013-09-24T15:55:44.807 に答える
1

したがって、これを実現するには「二重ディスパッチ」を使用する必要があります。なんて下品。

基本的に、ウィキペディアのリンクが言うように、

問題は、C++ では仮想関数が動的にディスパッチされる一方で、関数のオーバーロードが静的に行われることです。

したがって、あなたがしなければならないことは変更することですclass Cat

struct Cat : public Animal
{
  virtual void talkTo( Animal* o ) {
    //puts( "Cat-Animal" ) ;
    o->talkTo( this ) ; // TURN THE INVOKATION AROUND ("double dispatch")
  }
  virtual void talkTo( Cat* o ) {
    puts( "Cat says meow to Cat" ) ;
  }
} ;

cat->talkTo( animalCatPtr ) ;

animalCatPtr実際にはですCat*。しかし、talkTo関数は、 で「呼び出しを元に戻す」まで、それを知りませんCat::talkTo( Animal* )

animalCatPtrが実際には のみの場合、それが利用可能な場合、またはその関数のみが利用可能な場合に呼び出して、Animal最終的に基底クラスになります。AnimalAnimal::talkTo( Cat* )Animal::talkTo( Animal* )

animalCatPtrが実際に である場合、必要な動作である をCat呼び出すことになります。Cat::talkTo( Cat* )

于 2013-09-24T16:29:38.810 に答える