Spesso mi imballo alcuni dati in class
per evitare errori con accesso pubblico/globale e per fornire alcuni metodi comuni su di esso, ad esempio:"onEachSubelement (...)" metodo per C++
class GameArea{
std::vector<Enemy*> enemies;
std::wstring name;
public:
void makeAllEnemiesScared();
Enemy * getEnemy(unsigned index);
};
GameArea
è solo un esempio semplificato qui. Sarebbe una specie di container/menager personalizzato con alcuni metodi specializzati (ma non è solo un contenitore).
La situazione ideale è quando so che cosa saranno eseguite operazioni su ogni Enemy
subito e si verificano in diversi luoghi modo che io possa dichiarare GameArea
direttamente (come makeAllEnemiesScared()
).
Per gli altri casi posso andare con:
for(unsigned i=0; i<gameArea->getEnemiesCount(); i++){
Enemy * enemy = gameArea->getEnemy(i);
...
}
Ma soffre di alcuni svantaggi:
- non posso usare C++ 11 pulito & bello
for(auto &Enemy : enemies)
ciclo, - Non è efficiente (così tante chiamate allo
getEnemy(index)
), - Non è un scopo per
getEnemy(index)
per iterare gettare tutti gli elementi - è utile nel caso in cui vogliamo selezionare solo uno o alcuni di essi, ha anche il controllo perindex < enemies.size()
all'interno - è terribile controllarlo su ogni elemento in loop.
NOTA: penso a casi in cui faccio qualcosa di molto speciale (non vale la pena la creazione di metodo separato in GameArea
, ma su ogni elemento diGameArea::enemies
).
Ho pensato ad un metodo GameArea::onEachEnemy(... function ...)
che prende come parametro un function
(o forse meglio un lambda?). Questa è una buona soluzione?
O forse un approccio diverso dovrebbe essere usato qui? Come restituire il std::vector
da GameArea
- che mi sembra un po '"brutto". Non voglio che l'utente pensi che possa effettivamente aggiungere o rimuovere elementi da/a quello vector
direttamente.
Il tuo suggerimento "onEachEnemy" mi suona bene. – molbdnilo
Suppongo che tutto il comando 'getEnemy' sia quello di restituire' nemici [i] '? Quindi è possibile allineare la funzione e il compilatore molto probabilmente ottimizzerà la chiamata. È inoltre possibile evitare la ripetuta chiamata 'getEnemiesCount' chiamandola prima del ciclo e salvando il risultato. Puoi anche fornire un'interfaccia iteratore o, come ti chiedi, creare una funzione "per ogni". Ma prima di tutto dovresti probabilmente profilare il tuo programma per vedere se questo è davvero il collo della bottiglia che pensi sia. –
Oh, e ricorda che la funzione vector 'operator []' non esegue alcun controllo dei limiti, presuppone che l'utente del vettore abbia cura di non andare fuori limite. Se sei così preoccupato dell'inefficienza, probabilmente dovresti fare lo stesso, cioè eliminare i limiti controllando da 'getEnemy'. Ma come ho detto nel mio precedente commento, * profile * prima, e assicurarmi che questo sia davvero inefficiente come pensi tu sia. –