c ++ передача неизвестного типа в функцию и любое определение типа Class - PullRequest
1 голос
/ 23 мая 2010

Я пытаюсь создать универсальный класс для записи и чтения объектов в / из файла.Вызывается это ActiveRecord класс

имеет только один метод, который сохраняет сам класс:

void ActiveRecord::saveRecord(){
 string fileName = "data.dat";

 ofstream stream(fileName.c_str(), ios::out);
 if (!stream) {
  cerr << "Error opening file: " << fileName << endl;
  exit(1);
 }
 stream.write(reinterpret_cast<const char *> (this), sizeof(ActiveRecord));
 stream.close();
}

теперь я расширяю этот класс с классом пользователя:

class User : public ActiveRecord
{
 public:
  User(void);
  ~User(void);
  string name;
  string lastName;
};

чтобы создать и сохранить пользователя, я хотел бы сделать что-то вроде:

User user = User();
user.name = "John";
user.lastName = "Smith"
user.save();

как я могу получить этот метод ActiveRecord :: saveRecord () для получения любого объекта и определения класса, чтобы он записывал все, что я отправляю:

, чтобы выглядеть следующим образом:

void ActiveRecord::saveRecord(foo_instance, FooClass){
 string fileName = "data.dat";

 ofstream stream(fileName.c_str(), ios::out);
 if (!stream) {
  cerr << "Error opening file: " << fileName << endl;
  exit(1);
 }
 stream.write(reinterpret_cast<const char *> (foo_instance), sizeof(FooClass));
 stream.close();
}

и пока мы находимся, какой тип объекта по умолчанию в c ++.например.в target-c это id в java, это Object в AS3, это Object, что это в C ++ ??

Ответы [ 2 ]

5 голосов
/ 23 мая 2010
stream.write(reinterpret_cast<const char *> (foo_instance), sizeof(FooClass));

Это не работает. string распределяет свои данные в куче (IIRC, если он больше 16 символов). Ваше повторное толкование не будет включать эти данные кучи.

Не изобретайте велосипед, это нетривиальная, но решаемая проблема. Используйте буфер протокола Google , XML или улучшенную библиотеку сериализации .

Что вы имеете в виду, это шаблоны, но вы не можете "просто сериализовать любой объект", потому что за пределами типов POD (plain-old-data) их представление не очевидно.

Кроме того, использование sizeof(BaseClass) с подклассом User не будет работать. Он отрежет данные члена подкласса от приведения и не поместит их в файл.

И «Тип объекта по умолчанию в c ++» отсутствует.

1 голос
/ 23 мая 2010

То, что вы предлагаете, не выполняет глубокую сериализацию, вы вообще не можете знать, какие ресурсы хранит объект.
Чтобы позволить ему хранить любой объект, вы должны использовать функцию шаблона и делегировать фактическое сохранение рассматриваемому классу или его другу (т.е. operator<<()):

template<class T> void ActiveRecord::saveRecord(const T& foo) {
    // ...
    stream << foo;
    // ...
}

Чтобы это работало, вы должны предоставить перегрузки для operator<<() для рассматриваемых классов:

class Foo {
    friend std::ostream& operator<<(std::ostream&, const Foo&);
    // ...
    int a, b;
    // ...
};

std::ostream& operator<<(std::ostream& o, const Foo& f) {
    o << f.a << f.b;
    // ...
    return o;
}

Но, как сказал Стивен, почему бы не использовать проверенные решения для сериализации, вместо того, чтобы использовать свои собственные?

...