Как создать класс C ++? - PullRequest
       18

Как создать класс C ++?

0 голосов
/ 31 августа 2009

Я написал приложение в MFC с C ++. Мне нужно написать класс, который может сохранить все данные, загруженные из базы данных. Эти данные могут содержать все типы данных, такие как int, string, byte, boolean, datetime и так далее. Мы можем фильтровать, обмениваться столбцами или сортировать эти данные. Например:

int int string bool    double  float .... string
0    1   "a"    false   3.14    3.0        "b"
1    2   "5"    true    3.22    4          "c"

Примечание: Мы не использовали SQL для сортировки или фильтрации, так как у нас есть соображения.

Мы написали следующий класс, может, у кого-то есть лучшее предложение, пожалуйста, напишите пример класса для использования, заранее спасибо!

#ifndef __LIST_DATA_MODEL_H__
#define __LIST_DATA_MODEL_H__

#include <vector>
using std::vector;

///implement a pure virtual base class; parameters of function is a void pointer, 

class FieldType
{
public:
 enum {
  TypeChar    = 0,
  TypeString  = 1,

  TypeBool    = 2,

  TypeShort   = 3,
  TypeUShort  = 4,

  TypeInt     = 5,
  TypeUInt    = 6,

  TypeLong    = 7,
  TypeULong   = 8,

  TypeLongLong  = 9,
  TypeULongLong = 10,

  TypeFloat     = 11,
  TypeDouble    = 12
 };
};

template <typename _ValueType, typename _SyncType>
class Column
{
protected:
 CString       m_szFieldName;
 vector<_ValueType> m_vValues;

public:
 Column();
 Column(CString szFieldName);
 Column(const Column& other);
 virtual ~Column();

public:
 virtual BOOL LoadData(...);

public:
 ///This function will call LoadData function to re-load data, 
 ///if subclass this class, please implement your LoadData function 
 ///if you want additional operation when load data.
 CALLBACK BOOL Update();

public:
 const int   ValueCount() const;
 const CString&  FieldName() const;
 const _ValueType&   ValueAt(int iPos) const;

 ///Before you call LoadData function or Update Function, the values will not updated;
 void SetFieldName(const CString& szFieldName);

 void SetValue(const _ValueType& val, int iPos);
};

template<class _Type>
class DataItem
{
protected:
 _Type _value;

public:
 DataItem();
 DataItem(const DataItem& other)
 {
  _value = other._value;
 };
 DataItem(const _Type& val)
 {
  _value = val;
 };
 virtual ~DataItem()
 {
 };

public:
 const _Type& GetValue()
 {
  return _value;
 };
 void SetValue(const _Type& value)
 {
  _value = value;
 };
 void ResetValue()
 {
  _value = _Type();
 };
public:
 bool operator ==(DataItem& right)
 {
  return _value == right._value;
 };
 bool operator <(const DataItem& right)
 {
  return _value < right._value;
 };
 const DataItem& operator =(const DataItem& right)
 {
  if(this == &right)
   return *this;

  _value = right._value;

  return *this;
 };

 virtual DataItem* Clone()
 {
  return new DataItem(*this);
 };
};

typedef DataItem<int>  IntItem;
typedef DataItem<float>  FloatItem;
typedef DataItem<double> DoubleItem;
typedef DataItem<CString> StringItem;
typedef DataItem<bool>      BoolItem;
typedef DataItem<TCHAR>     CharItem;
typedef DataItem<char>      ByteItem;
typedef DataItem<CString>   CStringItem;

#endif

Ответы [ 5 ]

2 голосов
/ 31 августа 2009

Мой первый подход - использовать вариант повышения или повышение любого вместо создания своего собственного.

1 голос
/ 31 августа 2009

Мне интересно, если вы эмулируете поведение БД, имеет ли смысл хранить данные в контейнерах типа? Поскольку доступ к данным будет осуществляться через имена столбцов, у вас должны быть контейнеры, в которых хранятся значения данных для каждого столбца и сопоставление имени столбца с типом столбца. В любом случае, если вы хотите хранить данные вместе с их типом, рассмотрите следующий подход с использованием 'stringization of enums': -

  1. Создайте свой список константы для типов. Нравится enum MYTYPE { MYINT, MYFLOAT, ...}
  2. Записать информацию о БД после структурирования данных под каждым stringized-enum .
  3. Считать stringized-enum вместе с его данными в строковый контейнер, такой как std::vector<string>.
  4. Извлекает фактический тип перечисления из stringized-enum , а затем, используя простую инструкцию переключения регистра, преобразует строковые данные в фактические данные.

О том, как создавать строковые перечисления и использовать их, перейдите по ссылке здесь и здесь . Подход макроса. Или вы можете использовать шаблонизированный подход, который требует использования boost что-то вроде ниже (только подсказка :-)).

template<typename ENUM>
class Stringifier<ENUM, typename boost::enable_if<boost::is_enum<ENUM> >::type> {
  static const char * values[]; // array with the enum strings.
  static std::size_t size;      // Number of elements of the ENUM string arrays.
public:
  /// Global static instance of the Stringifier.
  static Stringifier & getInstance()
  {
    static Stringifier globalInstance;
    return globalInstance;
  }
  // Returns the string representation of the ENUM value \a e as a C string.
  // If string is not available an exception is thrown.
  virtual void str(ENUM const & e, std::string & s) const
  {
    if(e >= 0 && e < int(size))
      s = values[e];
    else // throw exception
     ;
  }

  // Returns the ENUM value of the string representation of an ENUM value if possible,
  // ENUM(0) otherwise or ENUM(size) if you like.
  virtual bool value(std::string const & str, ENUM & v) const
  {
    std::size_t i = 0;
    for(; i < size; ++i)
      if(values[i] == str) break;
    bool ok = (i != size);
    v = ok ? ENUM(i) : ENUM(0);
    return ok;
  }
};

Используйте ваше перечисление как 'ENUM' в вышеприведенном классе.

ПРИМЕЧАНИЕ : Стринизация убивает производительность. Так что этот подход медленнее.

1 голос
/ 31 августа 2009

Несколько замечаний по поводу вашего кода:

  • Как указывает MSalters, такие имена, как _ValueType и __LIST_DATA_MODEL_H__ недопустимы в коде пользователя.
  • Если виртуальная BOOL LoadData (...) является реальной сигнатурой функции, это тоже недопустимо - перед elipsis должен быть хотя бы один фактический параметр
  • Параметр шаблона _SyncType, похоже, не используется
  • тот факт, что вы перечислили все свои значения перечисления, дает мне подозрение, что вы собираетесь использовать эти числа явно позже - это плохая практика
  • Я действительно не вижу, что делает ваш класс, чего не делают сами _ValueTypes
1 голос
/ 31 августа 2009

Любая причина не использовать тип данных COM _variant_t?

0 голосов
/ 31 августа 2009

Это кажется мне чрезмерно сложным. Я бы реализовал столбец как простой вектор STL соответствующего типа, и я буду развиваться по мере необходимости. Постарайтесь не слишком задумываться об этой структуре данных, иначе вы создадите слишком сложный дизайн.

...