【问题标题】:When my base class and derived have the same function, does it HAVE to be virtual?当我的基类和派生类具有相同的功能时,它必须是虚拟的吗?
【发布时间】:2013-10-19 13:42:31
【问题描述】:

所以我有一个我正在从事的项目具有相当的层次结构。在 this 的基类中,有一个函数 reset() 会在所有派生类中被调用。我感到困惑的是,由于派生类中的重置基本上只是重置它的私有变量,然后调用它的前一个(更高)类的重置()函数,重置函数必须是虚拟的吗?

例如。

class Base
{
private:
   int some;
public:
   void reset();
};

class Derive : public Base
{
private:
   int some1;
public:
   void reset();
};

class Derive_two : public Derive
{
private:
   int some2;
public:
   void reset();
};

所以基本上 Derive_two 类的重置函数如下所示。

void Derive_two::reset()
{
   some2 = 10;
   Derive::reset();
}

这段代码对吗?还是函数 reset() 需要是 virtual 类型的?

感谢您的任何帮助。

【问题讨论】:

  • 嗯,我明白了。所以基本上,如果我希望派生类覆盖基类函数,我会将其设为虚函数。非常感谢 =)
  • 到目前为止,我已经看到了许多reset 的实现,这通常比其他任何事情都更容易造成维护负担。如果您不再需要某个物品,请将其扔掉。如果您需要一个新对象,请构建一个新对象。
  • @MatthieuM。老实说,我宁愿没有 reset() 功能,因为它确实是一种负担。但是,不幸的是,该程序被另一个程序标记,该程序检查 reset() 函数,而不是该程序是否执行了它应该做的事情。

标签: c++ virtual class-hierarchy


【解决方案1】:

这段代码对吗?

可能不会。它不是多态;这意味着通过指针或对Base 的引用调用函数只会调用Base 中声明的版本。所以如下:

void DoStuffAndReset(Base & b) {
    DoStuff(b);
    b.reset();
}

Derive d;
DoStuffAndReset(d);

不会完全重置d,只会重置它的基类部分,这几乎肯定不是您想要的行为。

或者函数reset()是否需要是虚拟类型的?

如果您想覆盖它,并且通过指针或对基类的引用可以调用覆盖的版本,则需要它;这可能是您想要的行为。通过将reset 设为虚拟,我的示例将完全重置对象,无论它是什么类型。

同样,您可能需要一个虚拟析构函数,以便可以通过指向基类的指针正确删除对象。事实上,以下看似无害的代码实际上具有未定义的行为:

Base * b = new Derive;
delete b;

可以通过在Basepublic 部分添加析构函数来修复:

virtual ~Base() {}  // assuming it doesn't need to do anything

【讨论】:

  • 基类的析构函数应该是either virtual OR protected,这取决于是否应该调用delete是否在指向基址的指针上。此外,复制构造函数和复制分配运算符应为 protected 以帮助防止意外切片。
【解决方案2】:

这取决于你的意图。您可以将此功能设为虚拟或非虚拟。例如考虑以下函数

void f( Base &b )
{
    b.reset();
}

int main()
{
    Derive d1;
    f( d1 );
    Derive_two d2;
    f( d2 );
}

所以问题是您是否希望该函数 f 仅重置基本子对象的数据成员,还是应该重置通过引用传递给它的对象的数据成员。

【讨论】:

    【解决方案3】:

    这个类似的 StackOverload 问题解释了虚拟方法并提供了一个很好的例子:

    Why do we need Virtual Functions in C++?

    如果这不能回答您的问题,请告诉我。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-11-03
      • 2013-08-25
      • 2016-08-13
      • 2019-11-04
      • 1970-01-01
      • 2015-10-24
      • 1970-01-01
      • 2011-06-21
      相关资源
      最近更新 更多