как сбросить большое количество учеников за раз, а не в деструкторе? - PullRequest
1 голос
/ 10 января 2011

У меня есть класс, содержащий много членов простого типа класса.Что еще более важно, их число растет, поскольку я продолжаю развитие.

Мне нужно иметь возможность сбросить их все сразу, и я бы хотел сделать это без их копирования.Код в настоящее время выглядит следующим образом:

typedef auto_ptr<odbc::PreparedStatement> Stmt;

class DbProxy {
private:
  void reset();

  Stmt a;
  Stmt b;
  Stmt c;
  // ... about 10 more
};

void DbProxy::reset()
{
  a.reset();
  b.reset();
  c.reset();
  // etc.
}

Очевидно, что мне не нравится добавлять каждый новый элемент в функцию reset() (только что произошла ошибка сегмента для того, чтобы забыть один).

Что я собираюсь сделать, это собрать их все в структуру и выделить эту структуру в auto_ptr.Таким образом, код будет выглядеть следующим образом:

typedef auto_ptr<odbc::PreparedStatement> Stmt;

class DbProxy {
public:
  DbProxy(): stmts(new OdbcResources) {}
private:
  void reset() { stmts.reset(); }

  struct OdbcResources {
    Stmt a;
    Stmt b;
    Stmt c;
    // ... about 10 more
  };
  auto_ptr<OdbcResources> stmts;
};

Объекты DbProxy не предназначены для копирования или создания копии, хотя я не удосужился обеспечить это, сделав назначение и copy-ctor закрытым.

Видите ли вы какие-либо проблемы с этим подходом?Есть ли у вас другие предложения?

РЕДАКТИРОВАТЬ

на основе предложения @DeadMG, что по этому поводу:

class DbProxy {
public:
  DbProxy();
private:
  enum Statements { SELECT1, SELECT2, INSERT, LAST };  // never mind the names

  void reset() { for (int i=0; i < LAST; i++) statement[i].reset(); }

  Stmt statements[LAST];
};

Ответы [ 5 ]

3 голосов
/ 10 января 2011

Использовать массив статического размера.

Stmt statements[10];

for(int i = 0; i < sizeof(statements) / sizeof(Stmt); i++)
    statements[i].reset();
2 голосов
/ 10 января 2011

Нет необходимости в дополнительных auto_ptr (каждый Stmt в любом случае auto_ptr), если вы соберете их в один класс, вы можете сбросить их с помощью простого назначения.В отличие от решения с массивами, вы по-прежнему сохраняете их значимые имена.

Обратите внимание, что вы не можете использовать неназванный временный (например, stmts = OdbcResources();), поскольку сгенерированный оператор присваивания копии примет ссылку не constчлены (auto_ptr) не могут быть назначены из не- const auto_ptr с.

class DbProxy {
public:
  DbProxy() : stmts() {}
private:
  void reset() { OdbcResources tmp; stmts = tmp; }

  struct OdbcResources {
    Stmt a;
    Stmt b;
    Stmt c;
    // ... about 10 more
  };
  OdbcResources stmts;
};
1 голос
/ 10 января 2011

Я не вижу ничего плохого в таком подходе.Это похоже на идиому «Частная реализация».Вас могут заинтересовать детали .

my2c

1 голос
/ 10 января 2011

Это требование для контейнера - при условии, что odbc::PreparedStatement можно скопировать, просто укажите их вектор в DbProxy

class DbProxy {
private:
  void reset() { resources.clear(); } // all vanish!

  vector<odbc::PreparedStatement> resources;
};

Иначе, shared_ptr

typedef shared_ptr<odbc::PreparedStatement> Stmt;
class DbProxy {
private:
  void reset() { resources.clear(); } // all vanish!

  vector<Stmt> resources;
};
0 голосов
/ 10 января 2011

Вы можете просто скопировать копию по умолчанию:

void reset() { *this = DbProxy(); }
...