C ++我是否正确理解多态性?

时间:2011-04-14 15:35:12

标签: c++ polymorphism derived-class override

Bar和Box是Foo的派生类,Foo有虚函数F(),Bar和Box都有函数F()。根据我的理解,多态性正确地允许Bar.F()而不是Box.F()或Box.F()而不是Bar.F()使用一些运行时例程覆盖Foo.F()而不知道您的对象是否是酒吧或盒子。它是这样的:

Foo * boxxy = new Box;
boxxy->F();

最后一行将调用右F()(在本例中为Box.F()),与boxxy是Box还是Bar或Foo无关(在这种情况下,虚拟Foo.F的实现)被称为)。

我明白这一点吗?如果boxxy是Box指针会发生什么变化?如果派生类没有F()的覆盖会发生什么?最后,为了避免为基类实现一个函数但仍然允许多态,你是否只编写一个空函数体并将其声明为虚拟?感谢。

5 个答案:

答案 0 :(得分:2)

几乎正确 - 考虑这个继承树:

      Foo
     /   \
   Bar   Box

如果你现在制作一个这样的指针:

Bar* barry = new Box();

您将获得nice compiler error,因为Box无法转换为Bar。 :)
所以它只有Foo<->BarFoo<->Box,而不是Bar<->Box。 接下来,当boxxyBox指针时,它只会调用Box::F函数(如果已提供)。
最后,为了强制子类实现某个函数,你将它声明为pure virtual,如下所示:

virtual void Func() = 0;
//   note this --- ^^^^

现在子类(在这种情况下为BarBox),必须实现Func,否则它们将无法编译。

答案 1 :(得分:1)

是的,将根据您通过Foo指针创建的对象类型调用正确的F()。

如果boxxy是一个Box指针,你只能调用它的F()或它的一个派生类的F(),除非你对它的父类做了一个dynamic_cast然后调用F()。

为避免必须在基类中实现,您将其定义为纯虚拟,如下所示:

class Foo
{
public:
    virtual void F() = 0; //notice the = 0, makes this function pure virtual.

};

答案 2 :(得分:1)

  

如果boxxy是Box,会发生什么变化   指针?

它将允许访问未从Foo继承的Box方法。 Box指针不能指向Bar对象,因为Bar不是从Box派生的。

  

如果派生类会发生什么   没有F()的覆盖?

它将从基类继承F()的实现。

  

最后,要避免实施   基类的功能,但仍然   允许多态,你刚才写   一个空的函数体并声明它   虚拟?

它会起作用,但它不是一种做多态的正确方法。如果你不能为基类的虚函数提出具体的实现,那就使该函数成为纯虚函数,不要将它实现为空函数。

答案 3 :(得分:1)

如果你像这样声明Foo

class Foo
{
private:
  Foo() {};
public:
  void func() const { std::cout << "Calling Foo::func()" << std::endl; }
};

和Bar一样

class Bar : public Foo
{
private:
  Bar() {};
public:
  void func() const { std::cout << "Calling Bar::func()" << std::endl; }
};

然后

Foo* bar = new Bar();
bar->func();

将调用Foo :: func()。

如果你像这样声明Foo

class Foo
{
private:
  Foo() {};
public:
  virtual void func() const { std::cout << "Calling Foo::func()" << std::endl; } // NOTICE THE virtual KEYWORD
};

然后

Foo* bar = new Bar();
bar->func();

将调用Bar :: func()。

答案 4 :(得分:0)

  • 我明白这个吗?是的,如果该函数被声明为虚函数。
  • 如果boxxy是Box,会发生什么变化 指针?取决于是否 功能是否是虚拟的。一个虚拟的 功能总是会调用 适当的派生函数;一个 非虚函数会调用 基于类型的版本 指针。
  • 如果派生类会发生什么 没有F()的覆盖?它 将使用基类定义。
  • 最后,要避免实施 基类的功能,但仍然 允许多态,你刚才写 一个空的函数体并声明它 虚拟?你也可以宣布它是纯粹的 虚拟:virtual void F() = 0。任何 打算实例化的类 进入一个对象很多覆盖它 功能并给它一个适当的 实施