Как исправить и улучшить этот код C ++, используя шаблоны и наследование? - PullRequest
0 голосов
/ 14 декабря 2010

Я изучаю c ++ и примерно знаю, что хочу делать, но делаю это неправильно и очень устала.Как лучше (прежде всего, правильно) сделать что-то вроде этого:

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

1 Ответ

1 голос
/ 14 декабря 2010

Во-первых, ваше назначение неверно

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

Отменяет ссылку на неинициализированный указатель!

Я бы внес несколько изменений в ваш код, во-первых, при необходимости использовать vector<...> везде будет вызывать RSI, typedef это

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

Теперь реализация:

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
}

Теперь в вашей главной:

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

ТогдаВы можете вызывать каждый тип, например,

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

Это вносит минимальные изменения в ваш дизайн, если вы хотите полностью избежать типа BaseResult, вы можете шаблонировать все - но я не уверен, какие функции BaseResult дает вам и будет ли это возможно ..

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...