È bello che tutte le funzioni di setter restituiscano un riferimento all'oggetto in C++?È bello che tutte le funzioni di setter restituiscano un riferimento all'oggetto in C++?
risposta
È uno schema abbastanza utilizzabile se ci sono molte cose che devono essere impostate su un oggetto.
class Foo
{
int x, y, z;
public:
Foo &SetX(int x_) { x = x_; return *this; }
Foo &SetY(int y_) { y = y_; return *this; }
Foo &SetZ(int z_) { z = z_; return *this; }
};
int main()
{
Foo foo;
foo.SetX(1).SetY(2).SetZ(3);
}
Questo modello sostituisce un costruttore che prende tre interi:
int main()
{
Foo foo(1, 2, 3); // Less self-explanatory than the above version.
}
E 'utile se si dispone di una serie di valori che non hanno bisogno sempre da impostare.
Per riferimento, un esempio più completo di questo tipo di tecnica è indicato come "Named Parameter Idiom" nelle Domande frequenti su C++ Lite.
Ovviamente, se si utilizza questo parametro per i parametri denominati, è possibile dare un'occhiata a boost::parameter. Oppure potresti non ...
Non ci penserei. In genere, si pensa all'oggetto 'setter' come a quello.
Inoltre, se si imposta solo l'oggetto, non si dispone di un puntatore ad esso comunque?
Non tutti i setter, ma alcuni di loro potrebbero restituire il riferimento all'oggetto per essere utile.
tipo di
a.SetValues(object)(2)(3)(5)("Hello")(1.4);
Ho usato una volta molto tempo fa per costruire Generatore di espressioni SQL che gestisce tutti i problemi fughe e altre cose.
SqlBuilder builder;
builder.select(column1)(column2)(column3).
where("=")(column1, value1)
(column2, value2).
where(">")(column3, 100).
from(table1)("table2")("table3");
Non è stato possibile riprodurre le sorgenti in 10 minuti. Quindi l'implementazione è dietro le quinte.
Ho fatto cose simili per la costruzione di documenti XML in C++. La domanda qui sembra però riguardare i setter della proprietà generale. –
È possibile restituire un riferimento a this
se si vuole funzione della catena setter chiama insieme in questo modo:
obj.SetCount(10).SetName("Bob").SetColor(0x223344).SetWidth(35);
Personalmente ritengo che il codice è più difficile da leggere che l'alternativa:
obj.SetCount(10);
obj.SetName("Bob");
obj.SetColor(0x223344);
obj.SetWidth(35);
È una questione di layout. Puoi semplicemente scrivere la prima parte come la seconda, omettendo solo obj. su tutto tranne il primo e; su tutto tranne l'ultimo. IMHO, è leggibile allora. –
Se la tua motivazione è legata al concatenamento (ad esempio, il suggerimento di Brian Ensink), vorrei offrire due commenti:
1. Se sei tu Ti trovi spesso molte impostazioni contemporaneamente, il che potrebbe significare che dovresti produrre un struct
o class
che contenga tutte queste impostazioni in modo che possano essere tutte passate contemporaneamente. Il passo successivo potrebbe essere quello di usare questo struct
o class
nell'oggetto stesso ... ma dal momento che stai usando getter e setter la decisione di come rappresentarla internamente sarà comunque trasparente per gli utenti della classe, quindi questa decisione si riferiscono più alla complessità della classe che a qualsiasi altra cosa.
2. Un'alternativa a un setter è la creazione di un nuovo oggetto, la modifica e il suo ritorno. Questo è sia inefficiente che inappropriato nella maggior parte dei tipi, specialmente nei tipi mutabili. Tuttavia, è un'opzione che le persone a volte dimenticano, nonostante sia usata nella classe di stringhe di molte lingue.
Questa tecnica è utilizzata nello Named parameter Idiom.
Lo scopo tipico di questo stile è in uso per la costruzione di oggetti.
Person* pPerson = &(new Person())->setAge(34).setId(55).setName("Jack");
invece di
Person* pPerson = new Person(34, 55, "Jack");
Utilizzando il secondo più tradizionale stile si potrebbe dimenticare se il primo valore passato al costruttore era l'età o l'id? Questo può anche portare a più costruttori in base alla validità di alcune proprietà.
Utilizzando il primo stile si potrebbe dimenticare di impostare alcune delle proprietà dell'oggetto e può portare a bug in cui gli oggetti non sono "completamente" costruiti. (Una proprietà di classe viene aggiunta in un secondo momento ma non tutte le posizioni di costruzione vengono aggiornate per chiamare il setter richiesto.)
Come il codice si evolve Mi piace molto il fatto che posso usare il compilatore per aiutarmi a trovare tutti i luoghi dove viene creato un oggetto quando si modifica la firma di un costruttore. Quindi per questo motivo preferisco usare costruttori C++ regolari su questo stile.
Questo modello potrebbe funzionare bene in applicazioni che mantengono la loro datamodel nel corso del tempo in base alle leggi simili a quelle utilizzate in molte applicazioni di database:
- È possibile aggiungere un campo/attributo a un tavolo/classe che è NULL per impostazione predefinita. (Quindi l'aggiornamento dei dati esistenti richiede solo una nuova colonna NULL nel database.)
- Il codice che non è modifiche dovrebbe funzionare ugualmente con questo campo NULL aggiunto.
+1 per la sicurezza in fase di compilazione. – Eclipse
Wow. Questo è un incredibile adattamento alla mancanza di parametri con nome in C++ (come Ada ha avuto per 20 anni). –
-> no. per i puntatori però :) –
IMO setter sono un odore di codice che di solito indicano una delle due cose:
Fare Un Mountian un granello di sabbia
Se si dispone di una classe come questa:
class Gizmo
{
public:
void setA(int a) { a_ = a; }
int getA() const { return a_; }
void setB(const std::string & b) { v_ = b; }
std::string getB() const { return b_; }
private:
std::string b_;
int a_;
};
... e i valori sono davvero così semplici, quindi perché non rendere pubblici i dati solo ?:
class Gizmo
{
public:
std::string b_;
int a_;
};
... molto più semplice e, se i dati sono così semplice si perde nulla.
Un'altra possibilità è che si potrebbe essere
Fare un granello di sabbia da un Mountian
Un sacco di volte i dati non è così semplice: forse bisogna cambiare più valori, fare un po 'di calcolo, avvisare qualche altro oggetto; chissà cosa. Ma se i dati non sono abbastanza banali da avere davvero bisogno dei setter & getter, allora non è abbastanza banale da richiedere anche la gestione degli errori. Quindi in questi casi i tuoi setter & dovrebbero restituire una sorta di codice di errore o fare qualcos'altro per indicare che qualcosa di brutto è successo.
Se si concatenano le chiamate insieme in questo modo:
A.doA().doB().doC();
... e DOA() non riesce, non si vuole veramente di essere chiamata DOB() e DOC() in ogni caso? Ne dubito.
RE: "A.doA(). DoB(). DoC();" se doA fallisce, ecco a cosa servono le eccezioni. – Eclipse
+1, buon punto John. Inoltre, buon punto Josh. –
- 1. Elenca tutte le funzioni/simboli al volo in C?
- 2. È possibile ottenere un riferimento alla funzione di setter di un "setter"?
- 3. C# - Applicazione per mostrare tutte le dipendenze tra le funzioni?
- 4. Dovrei considerare che dichiarare tutte le funzioni statiche C è una buona pratica?
- 5. Ottieni un elenco di tutte le funzioni e le procedure in un database Oracle
- 6. Equivalente Python di LINQ Tutte le funzioni?
- 7. Elenca tutte le funzioni integrate in javascript?
- 8. rimuovere tutte le variabili tranne le funzioni
- 9. C# Memorizza le funzioni in un dizionario
- 10. Trova tutte le funzioni decorate in un modulo
- 11. Restituisce tutte le funzioni definite in un file Javascript
- 12. Che cosa c'è di così bello nell'ORM?
- 13. Perché constexpr non è l'impostazione predefinita per tutte le funzioni?
- 14. python - elenca tutte le funzioni interne di una funzione?
- 15. Qual è lo scopo dell'utilizzo di un riferimento a un riferimento in C++?
- 16. Perché è bello chiudere() un inputstream?
- 17. Cerca il testo di tutte le funzioni in PGAdmin
- 18. Creazione dell'app Visual C++ che non utilizza le funzioni CRT fa ancora riferimento ad alcuni
- 19. Eliminare tutte le funzioni dal database Postgres
- 20. Riferimento Newtonsoft.Json che si lamenta delle funzioni di Azure
- 21. Chiama le funzioni C/C++ da ExecutionEngine
- 22. Funzioni di setter e getter. In Android. Sovraccarico delle prestazioni?
- 23. Script per inserire la registrazione in tutte le funzioni di un progetto?
- 24. È vero che tutte le librerie c possono essere utilizzate in C++?
- 25. Come registrare all'interno di un decoratore tutte le funzioni che decora?
- 26. È bello inserire le operazioni jdbc negli attori?
- 27. Setter e getter in C++
- 28. Cerca tutte le funzioni esistenti per le dipendenze del pacchetto?
- 29. Carica tutte le funzioni in PowerShell da una determinata directory
- 30. Modifica del parametro predefinito comune in tutte le funzioni in un pacchetto
Sono stato incuriosito da questa tecnica ultimamente. Sarà interessante vedere se qualcuno presenta degli inconvenienti. –
Interessante. Non l'avevo considerato un'alternativa ai costruttori complessi. Questa tecnica potrebbe ridurre un numero elevato di sovraccarichi del costruttore. –
Ci sono alcune cose che non si possono fare con ciò che si può fare con i costruttori (ad esempio inizializzando Sali e riferimenti) – Eclipse