使用继承和模板的数据库接口
Database interface using inheritance and templates
我正在尝试实现一个简单的数据库接口,该接口可以处理不同类型的类型,包括自定义类。我想选择继承或模板,但似乎我同时使用了两者,但没有好的结果。
头文件
enum class RECORD_TYPE
{
TYPE_LONG = 11,
TYPE_STRING = 12
//other types
};
// the reason I created this class is to use it as function member parent
class RecordType
{
public:
RecordType(RECORD_TYPE record_type) : record_type_(record_type) {}
RECORD_TYPE get_record_type()
{
return record_type_;
}
protected:
RECORD_TYPE record_type_;
};
template<class T>
class RecordType_t : public RecordType
{
public:
RecordType_t(T value, RecordType type) : RecordType(type), value_(value) {}
const T &get_value() const { return value_; }
protected:
T value_;
};
class RecordType_long : public RecordType_t<long>
{
public:
RecordType_long(long value) : RecordType_t(value, RECORD_TYPE::TYPE_LONG) {};
};
class RecordType_string : public RecordType_t<std::string>
{
public:
RecordType_string(std::string value) : RecordType_t(value, RECORD_TYPE::TYPE_STRING) {};
};
用法
void add_record(const RecordType &record)
{
//here I need to know the type(string/long/custom) because the types have to be stored different
switch (record.get_record_type())
{
case RECORD_TYPE::TYPE_LONG:
//long x = record.get_value();
case RECORD_TYPE::TYPE_STRING:
//string x = record.get_value();
//then do something with these values
};
};
Database db;
RecordType_string str("test");
db.add_record(str);
RecordType_long lng(200);
db.add_record(lng)
我的主要问题(除了我很确定这是糟糕的设计这一事实)是,在函数 add() 中,我无法访问 get_value() 成员函数,因此我可以获取每种类型的值。因为,当然,在父类中,如果我创建 get_value(),我将不知道要返回什么类型。 你能建议如何更好地实现这件事吗?
谢谢
附言我可以从 RecordType 动态转换为 RecordType_long/RecordType_string/etc,但我在这里读到这真的是非常糟糕的设计:)
问题是模板提供了一种多态行为,该行为与继承提供的行为正交。
前者提供参数化多态性,而后者提供子类型化。
这两种不同类型的多态性不会C++混合在一起。每个模板专用化都是不同的类型,它与同一模板的其他专用化正交,这意味着这些类型之间没有像继承那样的关系。
因此,您的选择实际上取决于您打算使用的设计。例如,要让每种字段将自己保存在数据库中,您需要让每个实例管理自己的序列化,而无需知道哪个是谁,例如:
class SerializableRecord
{
public:
virtual void save(Database& db) const;
}
class RecordType_long : private RecordType_t<long>, public SerializableRecord
{
public:
void save(Database& db) const override {
long value = get_value();
/* save it on database somehow */
}
}
通过这种方式,您可以将多态性和模板一起使用,但用于两个不同的目的,而无需知道要保存哪种特定类型的记录,当然这也意味着您需要使用指针或发生对象切片。
另一种解决方案是使Database::save
模板化并专门针对各种类型的:
class Database {
public:
template<typename T> void save(const T& record);
}
template<> void Database::save<RecordType_t<long>>(const RecordType_t<long>& record) {
long value = record.get_value();
// ...
}
实际上你有很多选择,这实际上取决于你需要实现什么以及结构本身的复杂性。
相关文章:
- 查询SQLite数据库中的日期
- 有没有一种方法可以创建一个带有哈希表的数据库,该哈希表具有恒定时间查找功能
- 如何在ArangoDb AQL查询中指定数据库
- C++核心准则 C35 对于接口类"A base class destructor should be either public and virtual, or protected and nonv
- Visual C++GC接口如何启用它以及要包含哪个库
- 从数据库实时显示QT c++中的数据
- Windows.h与GLFW.h的接口
- 使用 pqxx 将 std::vector 存储在 postgresql 中,并从数据库中检索它
- 当字段可以为null时,如何使用C++接口在Avro中写入数据
- 提供与TMP和SFINAE的通用接口
- 无法在C++中建立与MySQL数据库的连接
- 为重写std::exception的库生成swig接口时出错
- 内联如何影响模块接口中的成员函数
- 将类实现到数据库程序中
- 连接 dockerized 模型和 dockerized 数据库时出现"无法 SQLConnect"错误
- COM 接口 c# 封送数组数组
- 使用继承和模板的数据库接口
- C++:数据库的通用接口设计
- 最容易使用的连接器/接口,将MySQL /其他数据库与C++一起使用
- 加速Oracle数据库在Qt (QOCI)中的接口