【问题标题】:Inheritance resolution继承解析
【发布时间】:2013-09-24 15:49:57
【问题描述】:

我认为类型会自动解析到他们可以层次结构的最深部分。如果Cat : Animal 并且你调用cat->talk(),如果Cat 覆盖talk()Animal 中的talk(),猫会说“喵喵”,而不是基类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

这里的最后一行,我将Cat 发送到cat->talkTo,但我使用的是animalCatPtranimalCatPtr 仍然指代Cat,但它在函数调用中解析为简单的Animal

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

【问题讨论】:

  • 只有void(Animal*) 成员函数被覆盖。另一个是 new 重载,仅在Cat 中定义。

标签: c++ inheritance overload-resolution


【解决方案1】:

您想要一种双重派送形式,请参阅http://en.wikipedia.org/wiki/Double_dispatch

【讨论】:

  • 也就是说,dynamic_cast<>()
  • @bobobobo - 一点也不,通过动态调度,您使用传递给动态对象的基指针以多态方式桥接到另一个成员函数。
  • 好的,我明白了。我added more info in an answer below
【解决方案2】:

所以你必须使用“双重调度”来实现这一点。多么粗鲁。

基本上,正如wikipedia link 所说,

问题在于,虽然虚函数在 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 实际上是Cat,那么我们最终将调用Cat::talkTo( Cat* ),这就是我们想要的行为。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多