Создайте много вложенных учеников - PullRequest
1 голос
/ 02 марта 2020

Я хочу создать базовый класс для обработки многих SQL операторов для разных систем баз данных.

Моя основная идея c заключалась в следующем:

struct BaseSQLStmts {

    BaseSQLStmts(Database db) : db(db) {};

    // nested operator class Cmd.
    struct Cmd {
        Cmd(Database db, const char *sqlStmt)
        : db(db), sqlStmt(sqlStmt), sqlHandle(Database::noHandle)
        {};


        Database::Handle operator() () {
            if (sqlHandle==Database::noHandle) {
                sqlHandle = db->prepareSQL(sqlStmt);
            }

            return sqlHandle;
        }

        Database db;
        const char *sqlStmt;
        Database::Handle sqlHandle;
    };

    // SQL-Statement to construct with database and SQL.
    Cmd theSqlStmt;

    // And many more (>50) members of type Cmd.

private:
    Database db;
};

// later use:
BaseSQLStmts *dbSql = new SQLStmtsClassForDB(db);
// ...
db->execute(dbSql->theSqlStmt());

Проблема в том, Как создать все члены (более 50) типа BaseSQLStmts::Cmd с базой данных и SQL -Statements путем создания производного класса. Я мог бы определить const char * параметр для каждого SQL в конструкторе, но это подверженное ошибкам количество параметров. Виртуальные функции-члены для получения именованных SQL операторов virtual const char* theSqlStmtSQL() = 0 не работали с конструктором (чисто виртуальный член). Построение внутри производного класса также не сработало.

Есть хорошая идея, как справиться с этим, проверив полноту операторов по времени компиляции?

Ответы [ 2 ]

1 голос
/ 02 марта 2020

Любая хорошая идея, как справиться с этим без использования сложных структур данных

Это противоречиво. Если у вас есть более 50 значений какого-либо типа, вы действительно должны рассмотреть возможность помещения их в какой-либо контейнер.

Конечно, ваши 50 запросов имеют что-то, чтобы их идентифицировать. Даже что-то вроде

enum Queries { CreateFoo, GetBarOfFooByBaz, ..., Queries_Count }

std::vector<Cmd> commands(Queries_Count);

будет полезно.

0 голосов
/ 02 марта 2020

Слишком много членов данных кажется мне запахом кода. Может быть, вы должны работать над своим дизайном для этого. Кроме того, ваш запрос не использовать «сложные структуры данных» кажется мне немного странным. Во-первых, вектор не так уж и сложен, а во-вторых, вы должны всегда использовать STL-контейнеры, если это уместно. Они быстрые, проверенные и надежные.

Увы, для того, что вы спросили, я думаю, что лучшим способом было бы поместить все Cmd в отдельный класс, заставить их использовать и хранить (указатель на ) объект в вашем BaseSQLStmts, то есть:

struct CmdCollection {
   struct Cmd {
        Cmd(CmdCollection &coll, const char *sqlStmt)
        : collec(coll), sqlStmt(sqlStmt), sqlHandle(Database::noHandle)
        {};


        Database::Handle operator() () {
            if (sqlHandle==Database::noHandle) {
                sqlHandle = collec.db->prepareSQL(sqlStmt);
            }

            return sqlHandle;
        }

        CmdCollection &collec;       
        const char *sqlStmt;
        Database::Handle sqlHandle;
    };

    Database db;
    Cmd cmd1 = Cmd(*this, "STMT1");
    Cmd cmd2 = Cmd(*this, "STMT2");

    CmdCollection(Database db) : db(db) {}
};

struct BaseSQLStmts {

    BaseSQLStmts(Database db) : db(db), col(db) {};    

    // SQL-Statement to construct with database and SQL.
    CmdCollection col;

    // And many more (>50) members of type Cmd.

private:
    Database db;
};
...