Pediram-me para fazer uma pequena alteração em um projeto antigo criado com o Visual Studio 2013 VC++. Então instalei o VS2013, fiz a alteração, compilei mas o comportamento dele mudou em um código que não mexi.
Após a atualização, um método virtual que estava chamando o método na classe derivada agora está chamando o método na classe base.
Não sou especialista em C++, mas posso ver que essa é uma prática ruim. Tudo o que quero saber é se houve alguma alteração significativa em C++ em torno disso, para que eu possa explicar à pessoa que me pediu para atualizar este projeto.
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, nullptr);
e se eu editar o DerivedItem assim:
class DerivedItem : public BaseItem
{
public:
virtual void SetValue(int first, int* second = nullptr)
{
};
}
o SetValue
no DerivedItem é chamado novamente.
A substituição de funções é baseada nos parâmetros e seus tipos, não levando em consideração os valores padrão. Após a alteração,
DerivedItem::SetValue
não é mais uma substituiçãoBaseItem::SetValue
, é apenas uma função membro que obscurece a função base de mesmo nome.Você pode fazer com que o compilador diagnostique isso usando a
override
palavra-chave sempre que desejar que a substituição aconteça:então ocorrerá um erro se a função não estiver realmente substituindo uma função da classe base (em oposição a uma mudança silenciosa no comportamento do tempo de execução).
Para substituir uma função você terá que fazer com que a assinatura da classe derivada corresponda à classe base, como você descobriu.
Na minha opinião - é mais limpo e robusto evitar totalmente os parâmetros padrão e adicionar outra sobrecarga da função para suportar um conjunto de parâmetros diferente. Então, em vez disso, a classe base teria:
e o derivado pode substituir um ou ambos. Essa abordagem também funciona melhor com o código existente que chama SetValue.