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

C++ C++;我是否正确理解多态性?,c++,polymorphism,derived-class,overriding,C++,Polymorphism,Derived Class,Overriding,Bar和Box是Foo的派生类,Foo有一个虚函数F(),Bar和Box都有函数F()。据我所知,多态性正确地允许Bar.F()而不是Box.F()或Box.F()而不是Bar.F()使用一些运行时例程重写Foo.F(),而不知道对象是Bar还是Box。是这样的: Bar* barry = new Box(); virtual void Func() = 0; // note this --- ^^^^ Foo*boxxy=新框 boxxy->F() 最后一行将调用右侧的F()(在本例中

Bar和Box是Foo的派生类,Foo有一个虚函数F(),Bar和Box都有函数F()。据我所知,多态性正确地允许Bar.F()而不是Box.F()或Box.F()而不是Bar.F()使用一些运行时例程重写Foo.F(),而不知道对象是Bar还是Box。是这样的:

Bar* barry = new Box();
virtual void Func() = 0;
//   note this --- ^^^^
Foo*boxxy=新框
boxxy->F()

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

我理解得对吗?如果boxxy是一个长方体指针,会发生什么变化?如果派生类没有F()的重写,会发生什么?最后,为了避免为基类实现函数,但仍然允许多态性,您是否只编写一个空函数体并将其声明为虚拟?谢谢。

  • 我理解得对吗?是,如果函数被声明为虚拟函数
  • 如果boxxy是长方体,会发生什么变化 指针?这取决于 函数是否为虚拟函数。虚拟的 函数总是以调用 适当的导出函数;A. 非虚拟函数将调用 版本取决于文件的类型 指针
  • 如果派生类 没有F()的重写吗?信息技术 将使用基类定义
  • 最后,避免实施 基类的函数,但仍然 允许多态性,你只是写吗 一个空函数体并声明它 事实上的你也可以宣布它是纯的 虚拟:
    virtual void F()=0
    。任何 要实例化的类 在一个对象中,要覆盖这一点 函数,并给它一个适当的 实施

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

      Foo
     /   \
   Bar   Box
如果现在创建如下指针:

Bar* barry = new Box();
virtual void Func() = 0;
//   note this --- ^^^^
由于
无法转换为
:),您将得到一个
所以它只是
FooBar
FooBox
,而不是
BarBox
。 接下来,当
boxxy
Box
指针时,它将只调用
Box::F
函数(如果提供)。
最后,为了强制子类实现某个函数,您将其声明为纯虚拟的,如下所示:

Bar* barry = new Box();
virtual void Func() = 0;
//   note this --- ^^^^
现在,子类(在本例中为
Bar
Box
)必须实现
Func
,否则它们将无法编译。

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

如果boxxy是一个长方体指针,则只能调用它的F()或它的一个派生类的F(),除非对它的父类执行动态_转换,然后调用F()

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

如果boxxy是长方体,会发生什么变化 指针

它将允许访问非从Foo继承的Box方法。长方体指针不能指向条形图对象,因为条形图不是从长方体派生的

如果派生类 没有F()的重写吗

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

最后,避免实施 基类的函数,但仍然 允许多态性,你只是写吗 一个空函数体并声明它 虚拟的


它会起作用,但这不是一种正确的方法。如果无法为基类的虚拟函数提供具体的实现,请将该函数设置为纯虚拟函数,不要将其实现为空函数。

如果您这样声明Foo

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


如果你像这样声明Foo

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

将调用Bar::func()。

非常感谢。只是出于好奇,你可以用NULL来代替0,对吗?@Brandon:不,不是在声明纯虚函数时。所需的exakt标记是
=0
,除此之外没有其他内容。另外,我鼓励您使用
0
而不是
NULL
,当C++0x出现时,使用
nullptr
作为指针: