首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将方法参数类型更改为子类中的派生类

问将方法参数类型更改为子类中的派生类
EN

Stack Overflow用户
提问于 2018-06-19 23:58:00
回答 3查看 67关注 0票数 1

我正在创建一个DB接口,并且有两个不同的数据库实现来使用这个接口

例如:

代码语言:javascript
复制
class DBOptions {
protected:
  DBOptions();
};

class SQLliteDBOptions : public DBOptions { bool verySpecificSQLiteOption; };
class MySQLDBOptions : public DBOptions{ bool verySpecificMySQLOption; };

class DBIface {
public:
  enum FileMode {
    READ = 1,
    WRITE = 2,
    READWRITE = 3
  };
public:
  virtual bool connect(char * filename, DBIface::FileMode mode, DBOptions * opt) = 0;
  virtual bool disconnect() = 0;
};

class SQLiteDB : public DBIface {
public:
  bool connect(char * filename, DBIface::FileMode mode, SQLliteDBOptions * options)
  { std::cout << "connect form sqlite\n"; }
  bool disconnect() { std::cout << "disconnect from sqlite\n"; }
};

class MySQLDB : public DBIface {
public:
  bool connect(char * filename, DBIface::FileMode mode, MySQLDBOptions * options)
  { std::cout << "connect form mysql\n"; }
  bool disconnect() { std::cout << "disconnect from mysql\n"; }
};

int main() {
  DBIface * sqlitedb = new SQLiteDB();
  SQLliteDBOptions * opt = new SQLliteDBOptions();
  sqlitedb->connect("file", DBIface::READ, opt);
  return 0;
}

两个派生类中的方法connect都不被视为父类中纯方法的实现。我应该怎么做才能解决这个问题?

我希望我的类接受正确的DB option实例。我认为我可以将DB选项动态转换为我需要的类型,但我想这不是最好的解决方案。

我应该创建一个setter方法来为每个DB实现设置DB选项吗?

EN

回答 3

Stack Overflow用户

发布于 2018-06-20 00:13:08

我建议将options参数作为派生数据库类型的构造函数的参数。这样,派生类型就可以要求正确的选项类型,而不必担心与基本签名匹配。只要options参数在任何虚拟方法上,那么它就必须是相同的(或者是通过逆差实现的基类型)。

票数 2
EN

Stack Overflow用户

发布于 2018-06-20 05:54:14

您必须在派生类中声明一个与纯虚方法connect()具有相同参数的方法。也就是说,除非覆盖所有纯虚函数,否则派生类也将被视为抽象类。

我尝试了SoronelHaetir提出的解决方案。正如预期的那样,它可以工作,我认为它以一种优雅的方式解决了您的问题。

代码语言:javascript
复制
class SQLiteDB : public DBIface{
public:
    SQLiteDB(SQLliteDBOptions* opt) { pOtps = opt; }
    bool connect(char * filename, SQLiteDB::FileMode mode)
    {
        std::cout << "connect form sqlite\n";
    }
    bool disconnect() { std::cout << "disconnect from sqlite\n"; }

private:
    SQLliteDBOptions * pOtps;
};



int main() {
    SQLliteDBOptions * opt = new SQLliteDBOptions();
    DBIface * sqlitedb = new SQLiteDB(opt);

    sqlitedb->connect("file", DBIface::READ);
    return 0;
}

当然,抽象基类中的虚函数必须进行相应的修改:

代码语言:javascript
复制
virtual bool connect(char * filename, DBIface::FileMode mode) = 0;
票数 0
EN

Stack Overflow用户

发布于 2018-06-21 03:23:25

我会完全摆脱connect和disconnect。此功能应分别移至派生类的构造函数和析构函数。每个构造函数可能有不同的签名,这是完全可以的,因为它们不是虚拟的。

这样,如果您有一个从DBIface派生的对象,您可以绝对确定它是连接的。

此解决方案符合RAII惯用法,因此可以推荐为首选选项。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50932513

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档