C ++函数覆盖

时间:2009-06-22 15:06:08

标签: c++ function polymorphism override

我有三种不同的基类:

class BaseA
{
public:
    virtual int foo() = 0;
};

class BaseB
{
public:
    virtual int foo() { return 42; }
};

class BaseC
{
public:
    int foo() { return 42; }
};

然后我从这个基础派生出来(用A代替X代替A,B或C):

class Child : public BaseX
{
public:
    int foo() { return 42; }
};

如何在三个不同的基类中重写该函数?我的以下三个假设是否正确?还有其他警告吗?

  • 使用BaseA,子类不编译,未定义纯虚函数。
  • 使用BaseB时,在BaseB *或Child *上调用foo时会调用子函数。
  • 使用BaseC时,在Child *上调用foo但在BaseB *上调用foo时调用子函数(调用父类中的函数)。

6 个答案:

答案 0 :(得分:16)

要记住的重要规则是,一旦函数声明为虚拟,派生类中具有匹配签名的函数始终是虚拟的。因此,对于A的Child和B的Child,它被覆盖,它的行为相同(除了你不能直接实例化BaseA)。

但是,使用C,函数不会被覆盖,而是会被重载。在那种情况下,只有静态类型很重要:它会调用它的指针(静态类型)而不是对象的真实类型(动态类型)

答案 1 :(得分:14)

在派生类中,如果在基类中将方法定义为virtual,则该方法是虚拟的,即使在派生类的方法中未使用关键字virtual。

  • 使用BaseA,它将按预期编译和执行,foo()为虚拟并在类Child中执行。
  • BaseB相同,它也将按预期编译和执行,foo()为virtual()并在类Child中执行。
  • 然而,对于BaseC,它将编译并执行,但如果您从BaseC的上下文和BaseC版本调用它,它将执行Child版本如果您使用Child
  • 的上下文进行通话

答案 2 :(得分:2)

  

使用BaseA,子类不会   编译,纯虚函数   未定义

只有在尝试创建BaseA对象时才会出现这种情况。如果您创建Child的对象,则可以使用BaseA *或Child *

调用foo()
  

使用BaseB,孩子的功能   在BaseB *上调用foo时调用   或儿童*。

取决于对象的类型,因为对象可以是BaseB或Child。如果对象是BaseB,则调用BaseB :: foo。

  

使用BaseC,孩子的功能   在Child *上调用foo时调用   但不是BaseB *(函数在   父类被称为。)

是的,但你永远不想这样做。

答案 3 :(得分:2)

从多态性的角度来看,更喜欢A,所以你知道每个孩子都有自己的虚函数实现。
如果您具有有效的默认实现,则主要选择B,但是您必须确保所有子类都根据需要具有自己的实现。 C不是多态,所以要明智地使用。

答案 4 :(得分:1)

这主要取决于你如何称呼它。

如果你这样做:

class Child : public BaseA
{
public:
    int foo() { return 42; }
};

并且做了

BaseA baseA = new Child();
baseA->foo();

它会调用Child的foo函数。

但是,如果你这样做了:

BaseA baseA = new BaseA();

会产生编译时错误。

答案 5 :(得分:0)

如果派生自A,

Class Child 编译,您无法实例化该类型的对象。

如果您要从Base覆盖某些函数,然后再次派生,这可能很有用。

相关问题