1

所以我有一个项目,我正在处理一个相当层次的项目。在 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() 需要是虚拟类型的?

感谢您的任何帮助,谢谢。

4

3 回答 3

2

这段代码对吗?

可能不是。它不是多态的;这意味着通过指针或引用调用函数Base只会调用Base. 所以以下内容:

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

Derive d;
DoStuffAndReset(d);

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

还是函数 reset() 需要是虚拟类型的?

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

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

Base * b = new Derive;
delete b;

可以通过在以下public部分添加析构函数来修复Base

virtual ~Base() {}  // assuming it doesn't need to do anything
于 2013-10-19T13:55:50.530 回答
1

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

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

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

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

于 2013-10-19T13:52:06.010 回答
0

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

为什么我们需要 C++ 中的虚函数?

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

于 2013-10-19T13:51:43.730 回答