2010-05-23 3 views
1

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

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

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(); 
} 

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

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++. например. в объекте-c его id в java это объект в AS3 это объект что это в C++ ??

+3

В C++ просто нет типа класса root. –

ответ

5
stream.write(reinterpret_cast<const char *> (foo_instance), sizeof(FooClass)); 

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

Не изобретайте велосипед, это нетривиальная, но решенная проблема. Используйте Google Protocol Buffers, XML или boost serialization library.

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

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

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

+0

+1 для не изобретать колесо. –

+0

Спасибо, ребята, за ответ. Замедленный курс, который я беру, кажется старым, как сам C++, требующий использования fstream. Поэтому я подумал, что я продолжу и еще немного отвлекусь. Так что это колесо, вроде у, я проверю эти lbraries.Thx – Bach

+0

@ user259789: Поскольку это для класса, вы, вероятно, хорошо разбираетесь в потоковом решении, которое описывает Георг ниже. Хорошо узнать немного о сериализации, прежде чем полностью опираясь на библиотеки. Несчастливой частью является то, что вам понадобится каждый класс, чтобы написать собственный потоковый писатель, вы не сможете написать общую версию, как вы пробовали. – Stephen

1

То, что вы предлагаете, не делает глубокой сериализации, вы не можете вообще знать, какие ресурсы хранит объект.
Для того, чтобы его сохранить любой объект, вы должны использовать шаблон функции и делегировать фактическое хранение в рассматриваемом классе или другом его (т.е. 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; 
} 

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

Смежные вопросы