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

时间:2018-06-19 15:58:00

标签: c++ inheritance polymorphism

我正在创建一个数据库接口,并使用两种不同的数据库实现方式来使用该接口

例如:

public foo()

两个派生类中的方法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; } 都不被视为父类中纯方法的实现。我应该怎么做才能解决这个问题?

我希望我的班级接受适当的数据库选项实例。我认为我可以将数据库选项动态转换为所需的类型,但是我认为这不是最佳解决方案。

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

3 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:0)

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

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

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

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

virtual bool connect(char * filename, DBIface::FileMode mode) = 0;

答案 2 :(得分:0)

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

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

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