2010-12-14 7 views
0

Ich lerne C++ und weiß ungefähr, was ich machen möchte, aber ich mache es falsch und bin sehr müde. Was ist der beste Weg (der richtige Weg, vor allem), so etwas wie dies zu tun:Wie korrigiert und verbessert man diesen C++ Code mit Templates und Vererbung?

// 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); 
} 

Antwort

1

Erstens ist Ihre Zuordnung nicht korrekt

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

De Verweise eines nicht-initialisierten Zeiger!

Ich würde ein paar Änderungen an Ihrem Code tun, erstens, vector<...> überall verwenden RSI induzieren wird, typedef es

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; 
}; 

Nun ist die Umsetzung:

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 
} 

Jetzt in Ihrem main:

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

Dann können Sie jedes t aufrufen wie z.B.

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

Dies führt zu minimalen Änderungen an Ihrem Design, wenn Sie die BaseResult Typ vollständig können Sie Vorlage alles vermeiden wollte - aber ich bin nicht sicher, welche Funktionalität BaseResult geben wird und ob dies möglich wäre ..

Verwandte Themen