2010-12-14 107 views
0

J'apprends le C++ et je sais à peu près ce que je veux faire, mais je le fais de travers et je suis très fatigué. Quelle est la meilleure façon (la manière correcte d'abord) de faire quelque chose comme ceci:Comment corriger et améliorer ce code C++ en utilisant les templates et l'héritage?

// Query.hpp 
class Query { 
public: 
Query(); 

template<typename T> 
std::vector<boost::shared_ptr<BaseResult> > run(); 

private: 
std::string sql; 
}; 

// Firstly, something like this: 
// I would like to do the equivalent of passing in a type T that would be 
// derived from BaseResult and create a new instance of it when adding 
// to vector of BaseResult: 
template<typename T> 
std::vector<boost::shared_ptr<BaseResult> > Query::run() { 
std::vector<boost::shared_ptr<BaseResult> > results; 

// ResultSet is from the mysql c++ connector 
boost::shared_ptr<sql::ResultSet> res(stmt->executeQuery(this->sql)); 

// I want to add a new T to results here 
while (res->next()) { 
    results.push_back(new T(res)); 
} 

// RVO prevents copy in release - yes? 
return results; 
} 

// Query.cpp 
Query::Query() { 
} 


// main.cpp 
void foo(const std::vector<boost::shared_ptr<BaseResult> >& results) { 
// loop through calling virtual method on each item 
} 

int main(int argc, char* argv[]) 
// Determine query type 
ProgramOptions opts(argc, argv); 

// Should this indeed be a pointer because 
// of code below or is it wrong? 
std::vector<boost::shared_ptr<BaseResult> >* results; 

    // Secondly, something like this: 
if (opts.getquerytype() == "type1") { 

    // I'd like to get a 
    // std::vector<boost::shared_ptr<BaseResult> > returned here 
    // containing many instances of a 
    // type derived from BaseResult 

    // I'd like to be able to do something like this 
    // Is this assignment correct? 
     *results = getQuery().run<DerivedResult>(); 
} 
else { 
    // I'd like to get a 
    // std::vector<boost::shared_ptr<BaseResult> > returned here 
    // containing many instances of a 
    // different type derived from BaseResult 

    // I'd like to be able to do something like this 
    // Is this assignment correct? 
     *results = getQuery().run<DifferentDerivedResult>(); 
} 

    foo(results); 
} 

Répondre

1

Tout d'abord, votre mission n'est pas correct

*results = getQuery().run<DifferentDerivedResult>(); 

De-fait référence à un pointeur non initialisées!

je ferais quelques changements à votre code, d'une part, d'avoir à utiliser vector<...> partout va induire le RSI, typedef il

class Query { 
public: 

// Query::ResultType 
typedef std::vector<boost::shared_ptr<BaseResult> > ResultType; 

Query(); 

// next, pass in the vector where the results will be stored... 
template<typename T> 
    void run(ResultType& records); 

private: 
std::string sql; 
}; 

Maintenant, la mise en œuvre:

template<typename T> 
void Query::run(ResultType& records) { 

// ResultSet is from the mysql c++ connector 
boost::shared_ptr<sql::ResultSet> res(stmt->executeQuery(this->sql)); 

// I want to add a new T to results here 
while (res->next()) { 
    records.push_back(new T(res)); 
} 

// No need to worry about RVO 
} 

maintenant dans votre principal:

Query::ResultType results; // not a pointer! 

Ensuite, vous pouvez invoquer chaque t ype, par exemple

getQuery().run<DifferentDerivedResult>(results); 

Cela introduit des changements minimes à votre conception, si vous voulez éviter le type BaseResult vous pouvez complètement modèle tout - mais je ne suis pas sûr de ce que la fonctionnalité BaseResult est de vous donner et si cela serait possible ..