2009-10-05 7 views
5

[EDIT 1 - ha aggiunto la sintassi terzo puntatore (grazie Alex)]C++ DAL - Ritorno di riferimento o popolano passata in riferimento

Quale metodo si preferisce per un DAL e perché fuori:

Car& DAL::loadCar(int id) {} 
bool DAL::loadCar(int id, Car& car) {} 
Car* DAL::loadCar(int id) {} 

Se non si riesce a trovare il primo metodo, la macchina restituisce null, il secondo metodo restituisce false.

Il secondo metodo creerebbe un oggetto Car sull'heap e popolerà con i dati interrogati dal database. Presumibilmente (mio C++ è molto arrugginita) che significherebbe codice lungo le linee di:

Car& DAL::loadCar(int id) 
{ 
    Car *carPtr = new Car(); 
    Car &car= *carPtr; 
    car.setModel(/* value from database */); 
    car.setEngineSize(/* value from database */); 
    // etc 
    return car; 
} 

Grazie

risposta

5

La seconda è decisamente preferibile. Stai restituendo un riferimento a un oggetto che è stato new'd. Per un utente finale che utilizza il software non è ovvio che l'oggetto restituito debba essere cancellato. PLUS se l'utente fa qualcosa di simile

Car myCar = dal.loadCar(id); 

Il puntatore andrebbe perso.

Il tuo secondo metodo mette quindi il controllo della memoria sul chiamante e impedisce che si verifichino strani errori.

Modifica: il ritorno per riferimento è ragionevole ma solo quando la classe genitore, cioè DAL, ha il controllo sulla durata del riferimento. cioè se la classe DAL avesse un vettore di oggetti Car in esso, restituire un riferimento sarebbe una cosa perfettamente sensata da fare.

Edit2: Preferirei ancora il secondo set up. Il terzo è molto meglio del primo ma si finisce col fare in modo che il chiamante presuma che l'oggetto sia inizializzato.

Si potrebbe anche fornire

Car DAL::loadCar(int id); 

E la speranza di accettare la copia dello stack.

Inoltre, non dimenticare che è possibile creare un tipo di oggetto auto null in modo da restituire un oggetto che è "valido" ish ma non restituisce alcuna informazione utile in tutti i campi (e quindi è ovviamente inizializzato con i dati della spazzatura). Questo è il modello oggetto nullo.

+0

Grazie. Anche se il chiamante ha scritto "Car & myCar = dal.loadCar (id)", il puntatore non andrebbe perso? Esiste comunque un codice non DAL per cancellare la memoria creata dal DAL? – ng5000

+0

No, se il chiamante ha scritto ciò che hai appena scritto, la memoria "potrebbe" essere liberata. Avresti bisogno di chiamare "delete &myCar;" per farlo però .. che sembra molto strano. – Goz

+0

La copia dello stack potrebbe anche non accadere: a seconda del compilatore e delle ottimizzazioni, il (N) RVO potrebbe dare il via e rendere l'operazione equivalente a # 1. In ogni caso sarà necessario lanciare un'eccezione quando l'auto non viene trovata. –

4

Poiché si assegna comunque oggetti su heap, perché non considerare Car * LoadCar() che restituisce NULL se si verifica un problema. In questo modo non hai restrizioni con i tipi di riferimento (ogni riferimento deve essere inizializzato) e hai anche i mezzi per segnalare il caso di errore.

+0

Invia una domanda ragionevole e aggiornata per aggiungere una terza opzione. – ng5000

+0

Car & DAL :: loadCar (int id) non può restituire NULL; non c'è riferimento null, solo puntatori nulli. – Massa