2012-04-23 14 views
6

Sto provando ad avere una classe che permetta il cast implicito a determinati tipi incorporati, come unsigned long int e poiché sto cercando di farlo nel modo più corretto possibile (questo è il mio primo progetto importante in C++), ho colpito un problema strano per quanto riguarda la correttezza const:Operatori di conversione da sovraccarico C++

questo funziona:

#include <iostream> 

class CustomizedInt 
{ 
private: 
    int data; 
public: 
    CustomizedInt(); 
    CustomizedInt(int input); 
    operator unsigned long int() const 
    { 
     unsigned long int output; 
     output = (unsigned long int)data; 
     return output; 
    } 
}; 

CustomizedInt::CustomizedInt() 
{ 
    this->data = 0; 
} 

CustomizedInt::CustomizedInt(int input) 
{ 
    this->data = input; 
} 

int main() 
{ 
    CustomizedInt x; 
    unsigned long int y = x; 

    std::cout << y << std::endl; 

    return 0; 
} 

Ma questo:

#include <iostream> 

class CustomizedInt 
{ 
private: 
    int data; 
public: 
    CustomizedInt(); 
    CustomizedInt(int input); 
    operator unsigned long int() const; 
}; 

CustomizedInt::CustomizedInt() 
{ 
    this->data = 0; 
} 

CustomizedInt::CustomizedInt(int input) 
{ 
    this->data = input; 
} 

CustomizedInt::operator unsigned long() 
{ 
    unsigned long int output; 
    output = (unsigned long int)data; 
    return output; 
} 

int main() 
{ 
    CustomizedInt x; 
    unsigned long int y = x; 

    std::cout << y << std::endl; 

    return 0; 
} 

mi dà questo errore in Visual Studio 2010: error C2511: 'CustomizedInt::operator unsigned long(void)' : overloaded member function not found in 'CustomizedInt'

Ora, se rimuovo la parola chiave const dalla definizione dell'operatore, tutto è OK. è un insetto? Ho letto che dovrei usare la parola chiave const dopo ogni metodo/operatore (pubblico) per affermare chiaramente che non altera l'oggetto corrente in alcun modo.

Inoltre, so che definire un simile operatore può essere una cattiva pratica, ma non sono sicuro di comprendere appieno le avvertenze associate. Qualcuno potrebbe descriverli per favore? Sarebbe meglio fare una semplice definizione di un metodo pubblico chiamato ToUnsignedLongInt?

risposta

8

firma La funzione non corrisponde alla definizione di funzione.

operator unsigned long int() const; 

e

CustomizedInt::operator unsigned long() { ... } 
             ^^^ 
            const missing 

In questo caso si dovrebbe contrassegnare l'operatore di conversione come const in quanto non influisce sullo stato interno dell'oggetto.

Inoltre, utilizzare gli elenchi di inizializzazione del costruttore per inizializzare le variabili membro.

CustomizedInt::CustomizedInt() 
: data() 
{ 
} 

CustomizedInt::CustomizedInt(int input) 
: data(input) 
{ 
} 
+0

Sì, grazie! Per qualche ragione, ho pensato che non ho bisogno di ripetere il const postpended nell'implementazione ...Per quanto riguarda i costruttori, sì, gli elenchi di inizializzazione sono utili, ma, nella mia reale implementazione, i dati hanno un tipo complesso e l'implementazione del costruttore è un po 'troppo complessa per gli elenchi di inizializzazione ... –

+0

@MihaiTodor Se 'data' ha un tipo complesso Direi che è una ragione in più per usare una lista di inizializzazione invece di un compito. Le [Domande frequenti su C++] (http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.6) spiegano perché è una buona pratica ed elenca anche alcune eccezioni a questa regola. – Praetorian

+0

Beh, sono completamente d'accordo, ma cosa fai se hai bisogno di chiamare certe funzioni per inizializzare quei dati? Sto usando la libreria GMP e i dati sono di tipo mpz_t, che deve essere inizializzato con mpz_init (...). Come posso chiamare la funzione mpz_init sui dati nella lista di inizializzazione? –

2

Sì, se la funzione membro non influisce sullo stato logico dell'oggetto, è quindi necessario postfix con const, in modo che il compilatore lo applicherà.

Ma in questo caso, è necessario aggiungere const quando si definisce il corpo della funzione!

+0

Hm ... Funziona! Per qualche ragione, non ha funzionato prima, ma penso di aver fatto un altro errore da qualche parte ... Grazie mille :) –

6

È potrebbe rimuovere il const dalla dichiarazione, ma quello che quasi certamente vuole fare è aggiungere alla definizione:

CustomizedInt::operator unsigned long() const 
{ 
    unsigned long int output; 
    output = (unsigned long int)data; 
    return output; 
} 
+0

Bene, ma cosa succede se l'implementazione di questo operatore è più grande del mio semplice esempio? Non voglio aggiungere 10 righe di codice di implementazione nell'intestazione, quindi voglio implementarlo al di fuori della classe ... –

+0

@ michael85: Lascia l'intestazione così com'è. Basta aggiungere il 'const' dove lo si implementa. Le due firme devono corrispondere. –

+0

Sì, ho capito. Grazie. –

1

Hai solo bisogno di copiare lo stesso prototipo di funzione nell'implementazione. ie.

CustomizedInt::operator unsigned long int() const 
+0

Yeap ... Grazie :) –

Problemi correlati