Domanda

Ho una classe base con un opzionale funzione virtuale

class Base {
    virtual void OnlyImplementThisSometimes(int x) {}
};

Quando compila questo ho un avviso circa la inutilizzati param x.C'è qualche altro modo mi hanno implementato la funzione virtuale?Ho ri-scritto questo:

class Base {
    virtual void OnlyImplementThisSometimes(int x) 
    {
        x = 0;
    }
};

Ho anche il problema che se non sto attento, la sottoclasse faccio il possibile implementare la funzione errata e quindi non mi accorgo che a causa di sovraccarico:ad es.

class Derived : public Base {
    void OnlyImplementThisSometimes(int x, int y) { // some code }
};

Derived d;
Base *b = dynamic_cast<Base *>(&d);
b->OnlyImplementThisSometimes(x); // calls the method in the base class

Il metodo della classe base è stato chiamato perché ho implementato la funzione derivata con un "int y" param ma non c'è nessun avviso di questo.Queste sono solo le trappole più comuni in C++ o ho frainteso funzioni virtuali?

È stato utile?

Soluzione

Ignorando i problemi di progettazione si può aggirare l'avviso del compilatore su un inutilizzati variabile omettendo il nome della variabile, ad esempio:

virtual void OnlyImplementThisSometimes(int ) { }

Erroneamente implementare il metodo corretto la firma, quando cercando di ignorare la funzione virtuale è solo qualcosa che hai bisogno di essere attenti in C++.Linguaggi come C# ottenere tutto questo con la "sostituzione" di parole chiave.

Altri suggerimenti

Possiamo definire una macro _unused come:

#define _unused(x) ((void)x)

Quindi definire la funzione come:

virtual void OnlyImplementThisSometimes(int x) { _unused( x );}

Questo non solo mantiene il compilatore da lamentarsi, ma rende evidente a chiunque di mantenere il codice che ti sei dimenticato x -- si sono intenzionalmente ignorarlo.

Perché definire nella classe base?Se la classe base non ha intenzione di utilizzare il metodo, quindi, definire solo come un metodo virtuale nella classe derivata.

O l'implementazione di default potrebbe generare un'eccezione

Se si fornisce una implementazione di default di una funzione virtuale, dovrebbe essere una corretta attuazione di tutte le classi derivate che non l'override della funzione.Se non è possibile fornire un corretto di attuazione, quindi il mio consiglio sarebbe quello di fare una funzione virtuale pura e lasciare che la classe derivata per fornire un'implementazione.Le classi derivate che non consentono il metodo chiamato, può generare un'eccezione per assicurarsi che esso non è utilizzato per errore.

Oltre a semplicemente omettendo il nome della variabile, in molti compilatori si può dire che il compilatore, che si è consapevoli che è inutilizzato e SHUTUP facendo questo

int func(int x)
{
   (void) x;
}

Questo è piuttosto comune, nel mio codice.Per esempio, io sono classi che sono progettati per singola operazione a thread e multi-threaded.Ci sono un sacco di routine comune e di dati.Ho messo tutto nella classe base, che ha un paio di puro virtuali).

Io l'implementazione di due vuoti virtuale funzioni della classe base:Init() e Cleanup().Il thread singolo classe derivata non impliment loro, ma il multi-threaded che si fa.

Ho una fabbrica di funzione di creare il approprite classe derivata quindi restituire un puntatore.Il codice del client conosce solo la base per il tipo di classe e si chiama Init() e Cleanup().Entrambi gli scenari fare la cosa giusta.

Naturalmente, ci possono essere altri ottimi consigli su come fare questo, ma questo stile funziona bene per un sacco del mio codice.

Non è una cattiva pratica e si tratta di un idioma comune per specificare le parti di una classe che sono facoltativi da implementare.

Attualmente lo sto usando per un utente di input del sistema, perché sarebbe noioso per un utente di quella classe per implementare ogni singolo metodo che è anche più probabile che non uso comunque.

class mouse_listener{
public:
    virtual ~mouse_listener() {}

    virtual void button_down(mouse_button a_Button) {}
    virtual void button_up(mouse_button a_Button) {}
    virtual void scroll_wheel(mouse_scroll a_Scroll) {}
    virtual void mouse_move_abs(math::point a_Position) {}
    virtual void mouse_move_rel(math::point a_Position) {}
};

Btw, se si conosce la classe base, non c'è mai bisogno di fare dynamic fino-getta, cioèderivati di base.

Base *b = &d;

Farà altrettanto bene, dynamic_cast<> dovrebbe, invece, essere utilizzato quando si e abbattuto, cioèdalla base di derivati:

if((Derived *d = dynamic_cast<Derived *>(b)) != 0)
{
  // use d
}

(E, naturalmente, in caso di fusione, static_cast<> di solito funziona così.)

Prova questo:

class Base {
    virtual void OnlyImplementThisSometimes(int x) = 0;
};

E ' stato un po da quando ho fatto cose del genere, ma credo che è come si dichiara una funzione virtuale.

Inoltre, come hanno detto gli altri, i nomi delle variabili sono opzionali in funzione di dichiarazioni come questa.

La risposta più semplice a questo è mostrato di seguito:

class Base {
    virtual void OnlyImplementThisSometimes(int x) { x;}
};

Un semplice riferimento alla variabile che non fa assolutamente nulla per rimuovere tutte le avvertenze (da VC++ a livello più alto comunque).

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top