Originariamente inviata da
Toxotes
ma ovviamente non so autovalutare il mio lavoro d'implementazione.
Il fatto è che non esiste un modo di procedere unico, anche se è possibile riconoscere vari "stili" di programmazione. Per cui il mio giudizio vale quanto il tuo se il codice funziona.
Un valido aiuto sullo "stile" lo trovi qui:
http://www.eptacom.net/pubblicazioni/cpp_stile/all.html
che se anche un po' datato è comunque un buon inizio.
In particolare ho dubbi sulla ripetizione degli header nei due file (forse il cpp può evitare di riscrivere gli header già inclusi nel .header annesso?, in questo caso solo <vector>, ma la domanda è generale, cioè c'è una prassi?).
No, nessuna prassi. Del resto se un header file è rindondante ci pensa il precompilatore a toglierlo. Piuttosto le righe:
codice:
#ifndef UNIFORM_DISTRIBUTION_CPP
#define UNIFORM_DISTRIBUTION_CPP
andrebbero tolte. Un file .cpp viene allegato in progetto una volta sola, non più di una come può avvenire nel corrispettivo .h per cui non ha senso porre una include guard in un file .cpp
Inoltre non so quale implementazione della funzione che genera un vettore di r.v. è il migliore. Grazie
Da qui inizia la mia personale visione della cosa: nessuna delle due mi piace.
Non sono generiche. Prendono un parametro fisso (il vector) che è un pò arbitrario, inoltre non consentono l'append di valori. Se un domani tu avessi bisogno di riempire una list, un set o un semplice array dovresti fornire degli overload per ognuno di questi tipi. Il mio consiglio è di lavorare sulla genericità prendendo spunto dalle interfacce degli algoritmi standard (utilizzano tutti solo iteratori e function objects).
Dovessi implementare io una classe simile scriverei:
codice:
class UniformDist {
private:
double _a, _b; //distributions' interval
public:
UniformDist(); //default constructor (default interval [0,1])
UniformDist(const double& a_, const double& b_); //parameter constructor
double get_a() { return _a; } //get _a
double get_b() { return _b;} //get _b
double operator()();
};
//default constructor
inline UniformDist::UniformDist(){
srand(time(0));
_a = 0;
_b = 1;
}
//parameter constructor
inline UniformDist::UniformDist(const double& a_, const double& b_) {
srand(time(0));
_a = a_;
_b = b_;
}
inline UniformDist::operator()() {
return (_b -_a)*(rand() / (double)RAND_MAX) +_a;
}
///////////////////////////
int main (etc) {
vector <double> v1(10);
std::generate(v1.begin(),v1.end(), UniformDist(1,3));
vector <double> v2;
std::generate_n(std::back_inserter(v1),20, UniformDist(1,3));
list<double> ls;
std::generate_n(std::back_inserter(ls),20, UniformDist(1,3));
set<double> myset(12);
std::generate(myset.begin(),myset.end(), UniformDist(1,3));
}
Ma come ho detto è solo una delle possibili implementazioni (e un personale punto di vista).