Ignora una funzione virtuale pura con argomenti predefiniti buona o cattiva?

2

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;
};
    
posta msc 04.08.2017 - 08:07
fonte

3 risposte

6

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.

    
risposta data 04.08.2017 - 15:38
fonte
3

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.

    
risposta data 04.08.2017 - 16:02
fonte
3

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!

    
risposta data 04.08.2017 - 15:22
fonte

Leggi altre domande sui tag