C++ 使用继承和模板的数据库接口

C++ 使用继承和模板的数据库接口,c++,templates,inheritance,C++,Templates,Inheritance,我试图实现一个简单的数据库接口,它可以处理不同的类型,包括自定义类。我想选择继承或模板,但似乎我使用了这两种方法,但效果都不好 头文件 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 { publ

我试图实现一个简单的数据库接口,它可以处理不同的类型,包括自定义类。我想选择继承或模板,但似乎我使用了这两种方法,但效果都不好

头文件

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\u long/RecordType\u 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 */
  }
}

实际上,您有很多选择,这取决于您需要实现什么以及结构本身的复杂性。

感谢您提供的详细答案,我考虑了第一种解决方案,因此RecordType具有一个以DB为参数的保存功能,而不是相反的方式。尽管从设计角度来看,DB可能应该是“更大”的实体,具有插入/更新/删除功能。我还将尝试第二种解决方案,看起来不错。:)
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();
  // ...
}