默认参数改变行为的虚拟方法

问题描述 投票:0回答:1

我被要求对使用 Visual Studio 2013 VC++ 构建的旧项目进行轻微更改。所以,我安装了 VS2013,进行了更改,编译了它,但它的行为在我没有接触过的代码上发生了变化。

更新后,调用派生类上的方法的虚拟方法现在正在调用基类上的方法。

我不是 C++ 专家,但我可以看到这是一个不好的做法。我只想知道 C++ 是否对此进行了重大更改,以便我可以向要求我更新此项目的人解释。

class BaseItem
{
  public:
    virtual void SetValue(int first, int* second = nullptr)
    {
    };
}

class DerivedItem : public BaseItem
{
  public:
    virtual void SetValue(int first)
    {
    };
}
BaseItem* item = new DerivedItem();
// Before: SetValue on the DerivedItem was called.
// After: SetValue on the BaseItem is called.
item->SetValue(5);

如果我像这样编辑 DerivedItem

class DerivedItem : public BaseItem
{
  public:
    virtual void SetValue(int first, int* second = nullptr)
    {
    };
}

再次调用

DerivedItem
上的 SetValue

c++ visual-c++ visual-studio-2013
1个回答
0
投票

函数重写基于参数及其类型,不考虑默认值。更改后,

DerivedItem::SetValue
不再是
BaseItem::SetValue
的重写,它只是一个隐藏同名基函数的成员函数。

每当您打算覆盖时,您都可以使用

override
关键字让编译器为您诊断这一点:

class DerivedItem : public BaseItem
{
    virtual void SetValue(int first) override

然后,如果该函数实际上并未覆盖基类中的函数(而不是运行时行为的静默更改),则会给出错误。


要重写函数,您必须使派生类签名与基类匹配,正如您所发现的那样。

在我看来——完全避免默认参数并添加另一个函数重载以支持不同的参数集会更干净、更健壮。因此,基类将具有:

virtual void SetValue(int first){ ... }
virtual void SetValue(int first, int second){ ... }

并且派生可以覆盖其中之一或两者。这种方法还可以更好地与调用 SetValue 的现有代码配合使用。

© www.soinside.com 2019 - 2024. All rights reserved.