1

我认为类型会自动解析到层次结构的最深部分。如果Cat : Animal你打电话cat->talk(),如果Cat覆盖一个talk()from 类Animal,猫会说“喵”,而不是基类中提供的一些奇怪的一般Animal抱怨Animal

所以我对此感到困惑:

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

这里的最后一行,我发送Catcat->talkTo,但我正在使用animalCatPtr. animalCatPtr仍然指的是 a Cat,但它只是Animal在函数调用中解析为 a 。

如何使传递指针解析为层次结构中最深的类型?我不想做一系列的dynamic_cast<>测试来看看Animal我手头的东西是否真的是一个CatDog或你有什么。

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,那么我们将在基类中结束Animal,调用Animal::talkTo( Cat* )它是否可用,或者Animal::talkTo( Animal* )如果只有那个函数可用。

如果animalCatPtr实际上是 a Cat,那么我们最终会调用Cat::talkTo( Cat* ),这是我们想要的行为。

于 2013-09-24T16:29:38.810 回答