当我的基类和派生函数具有相同的功能时,它是否必须是虚拟的?

时间:2013-10-19 13:42:32

标签: c++ virtual class-hierarchy

所以我有一个项目,我正在进行相当的层次结构。在这个基类中有一个函数reset(),它在所有派生类中被调用。所有我感到困惑的是,因为派生类中的这个重置基本上只是重置它的私有变量然后调用它的前面(更高)类'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类型吗?

感谢任何和帮助,谢谢。

3 个答案:

答案 0 :(得分:2)

  

这段代码是对的吗?

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

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

Derive d;
DoStuffAndReset(d);

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

  

或者函数reset()需要是virtual类型吗?

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

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

Base * b = new Derive;
delete b;

可以通过在public的{​​{1}}部分添加析构函数来修复:

Base

答案 1 :(得分:1)

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

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

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

所以问题是你是否希望函数f只重置基础子对象的数据成员,或者它应该重置通过引用传递给它的对象的数据成员。

答案 2 :(得分:0)

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

Why do we need Virtual Functions in C++?

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