L'override di una funzione virtuale pura con argomenti predefiniti è buona o cattiva?
class Base {
public:
virtual int func(int i, int j = 10) = 0;
};
class Derived : public Base {
public:
int func(int i, int j = 20) override;
};
Non oserei farlo. Nella migliore delle ipotesi, come @Bart van Ingen Schenau ha detto, ti ti causerà brutte sorprese. Inoltre, non raccomanderei nemmeno di usare i parametri di default nelle funzioni virtuali in primo luogo. Se vuoi avere qualcosa di simile, ti suggerisco di fare qualcosa del genere:
class Base {
public:
virtual int func(int i, int j) = 0;
virtual int func(int i)
{
func(i, 10);
}
};
class Derived : public Base {
public:
int override func(int i, int j)
{
//Some override code
}
int override func(int i)
{
func(i, 20);
}
};
Fornisci la funzionalità base con il metodo più specifico e fornisci metodi più semplici agli sviluppatori che usano le tue classi in modo che non debbano preoccuparsi dei valori di default per i parametri. In questo modo, hai una maggiore flessibilità di intervento e sai sempre quale metodo è stato chiamato e come.
In linea di principio, non c'è nulla di sbagliato nell'overridere una funzione con argomenti di default.
In pratica, c'è una grande possibilità che l'override contenga diverse impostazioni predefinite, che è un'enorme fonte di confusione e costernazione. Soprattutto se quelli modificati di default portano a un comportamento diverso, il codice ora non dipende solo dall'oggetto ma anche dalla conoscenza del sito di chiamata.
Quindi, evita di eseguire l'override delle funzioni con i valori predefiniti e, se davvero devi farlo, assicurati di fornire gli stessi valori di default in cui la funzione sostituita aveva i valori predefiniti, sebbene sia possibile aggiungerne altri.
Il solo fatto di avere funzioni non sostituibili con l'inoltro predefinito a una funzione protetta sovrascrivibile è un modo facile e raramente meno efficiente per evitare di sbagliare.
(È meno efficiente se lo spedizioniere non può essere inserito per qualsiasi motivo.)
Un modo diverso di guardare al problema è vedere una funzione con valori predefiniti non come una singola funzione, ma come una serie di sovraccarichi, solo uno dei quali è sovrascrivibile e può avere il proprio indirizzo.
Avere alcuni di questi sovraccarichi mancanti o fare qualcosa di diverso sarebbe una violazione del Liskov Principio di sostituzione per il tipo statico (importante per i modelli e il codice che scrivi direttamente), così come la funzione sovrascritta che viola il contratto della classe base sarebbe per il tipo statico e dinamico.
Modifica
È IS un'idea terribile ! Sebbene chiamerai il metodo sottoposto a override, otterrà i valori di default della classe base
codice c #
public class Base
{
public virtual int Func(int i = 10)
{
Console.WriteLine("base");
return i;
}
}
public class Derived : Base
{
public override int Func(int i = 20)
{
Console.WriteLine("derived");
return i;
}
}
Base b = new Derived();
Derived d = new Derived();
Console.WriteLine(b.Func());
Console.WriteLine(d.Func());
//ouput
derived
10
derived
20
codice c ++
#include <iostream>
#include <string>
class Base {
public:
virtual int func(int i = 10)
{
std::cout << "base";
return i;
};
};
class Derived : public Base {
public:
int func(int i = 20) override
{
std::cout << "derived";
return i;
};
};
int main()
{
Base* b;
Derived d;
b = &d;
std::cout << b->func();
std::cout << d.func();
}
//output
derived10derived20
Crazy!
Leggi altre domande sui tag object-oriented c++ virtual-functions c++14