使用元数据/继承来分解多个类的代码

时间:2015-05-22 06:58:31

标签: c++ templates inheritance metadata metaprogramming

我有两个代表两个非常简单的数据库的类,每个类都有一个" Save"将类中的内容写入文件的函数。由于" Save"功能非常相似,我想知道我是否可以将其考虑在内。

我的一位同事说这可能是继承和/或元数据的可能,所以我尝试用Google自己调查。但是,我找不到任何有用的东西,我仍然不确定我想做的事情是否可行。

如果它可以分解出来,那么我认为我需要让另一个类或函数了解每个类的类型并以某种方式迭代它们(元数据?)。它会检查每个数据的类型,并根据类型,确保它正确输出到文本文件。

(我知道名字,年龄等数据应该是私密的,但为了保持这个简单,我只需将所有内容公之于众)

class A
{
public:
  A() : name(""), age(0) {};

  void Save(void)
  {
    std::string filename = "A.txt";
    std::string data;

    data += name                + "\n";
    data += std::to_string(age) + "\n";

    std::ofstream outfile(filename);
    outfile.write(data.c_str(), data.size());
    outfile.close();
  }

  std::string name;
  int age;
};

class B
{
public:
  B() : ID(0), points(0) {};

  void Save(void)
  {
    std::string filename = "B.txt";
    std::string data;

    data += std::to_string(ID)     + "\n";
    data += std::to_string(points) + "\n";

    std::ofstream outfile(filename);
    outfile.write(data.c_str(), data.size());
    outfile.close();
  }

  int ID;
  int points;
};

int main(void)
{
  A a;
  B b;

  a.name = "Bob"; a.age    = 20;
  b.ID   = 4;     b.points = 95;

  a.Save();
  b.Save();

  return 0;
}

2 个答案:

答案 0 :(得分:1)

一种可能的解决方案可能是使用元编程(不确定您的元数据是什么意思),即重用公共部分的模板

template<typename T1, typename T2>
void TSave(const std::string fname, const T1& p1, const T2& p2) {
    std::string filename = fname;
    std::stringstream data;

    data << p1 << "\n";
    data << p2 << "\n";

    std::ofstream outfile(filename);
    outfile.write(data.str().c_str(), data.str().size());
    outfile.close();
}

class A {
  ...

  void Save(void) {
    TSave("A.txt", name, age);
  }

  std::string name;
  int age;
};

class B {
  ...

  void Save(void) {
    TSave("B.txt", ID, points);
  }

  int ID;
  int points;
};

Live Example

答案 1 :(得分:0)

您正在寻找的是serialization:将对象保存到文件中(以及一天或另一天,还原对象)。

当然,您可以编写自己的序列化框架,而Marco的答案是朝这个方向迈出的有趣开端。但另外,您可以考虑现有的库,例如boost::serialization

#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>

class A {
private: 
    friend class boost::serialization::access;
    template<class Archive>
    void serialize(Archive & ar, const unsigned int version)
    {
        ar & name;
        ar & age;
    }
...
};
class B {
private: 
    friend class boost::serialization::access;
    template<class Archive>
    void serialize(Archive & ar, const unsigned int version)
    {
        ar & ID;
        ar & points;
    }
...
};
main() {
   A a; 
   B b; 
   ...
   {
      std::ofstream ofs("myfile");
      boost::archive::text_oarchive arch(ofs);
      arch << a << b;
   }
}  

如您所见,仍然需要说出要写入文件的内容。但是,代码已经简化:您不必担心文件管理和数据转换。它也适用于标准容器。

你不会找到一个C ++技巧来自动确定一个类要保存什么。有两个原因:

  • C ++允许元编程,但它不是反身的:没有标准的过程可以在执行时找出哪些成员组成一个类。
  • 在一个对象中,某些数据可能是瞬态的,即它仅表示执行时的某些内容并且取决于上下文。例如指针:你可以保存指向文件的指针的值,但是当你稍后重新加载它时它将没有任何意义(指针只有在你释放对象之前才有效)。正确的方法是保存指向的对象(但在哪里,何时,如何?)。