Форум программистов, компьютерный форум, киберфорум
Наши страницы
Boost C++
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.57/7: Рейтинг темы: голосов - 7, средняя оценка - 4.57
sl_k
12 / 12 / 4
Регистрация: 15.04.2010
Сообщений: 61
#1

Буст сериализация. указатель на абстрактный базовый класс без конструктора по умолчанию

20.03.2013, 20:10. Просмотров 1276. Ответов 8
Метки нет (Все метки)

Читая документацию по сериализации с помощью буста запутался. Ситуация следующая. Имеется виртуальный базовый класс в Base.h:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#ifndef BASE_H
#define BASE_H
 
 
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include<new>
 
 
//declare the derived class
class base;
 
//declare new save and load function for non-defualt constructor
namespace boost {
    namespace serialization {
 
        template<class Archive>
            inline void load_construct_data(Archive & ar, test::base* t, const unsigned int file_version);
        template<class Archive>
            inline void save_construct_data(Archive & ar, const test::base* t, const unsigned int file_version);
 
    }
}
 
 
class Base{
   private:
         int a;
         int b;
         int c;
         //зафрендим сохранение и загрузку
        template<class Archive> friend 
              void boost::serialization::load_construct_data(Archive & ar, derived * t, const unsigned int file_version);
    template<class Archive> friend 
              void boost::serialization::save_construct_data(Archive & ar, const derived* t, const unsigned int file_version);
        friend class boost::serialization::access;
 
   public:
         //конструктор не по умолчанию
          Base(int a_, int b_, int c_): a(a_), b(b_), b(b_) {};
          virtual ~Base();
          virtual Foo() = 0;
 
 
};
 
//new load and save functions
namespace boost{
    namespace serialization {
        template<class Archive>
 
                    inline void load_construct_data(Archive & ar, Base* t, const unsigned int file_version)
                    {
                        
                        int a_;
                        int b_;
                        int с_;
                        ar >> a_;
                        ar >> b_;
                                                ar >> с_;
                        :: new(t) Base(a_,b_, с_);
                    }
        template<class Archive>
 
                    inline void save_construct_data(Archive & ar,const Base* t, const unsigned int file_version)
                    {
 
                        ar << t->a;
                        ar << t->b;
                        ar << t->с;
                        
                    }
    
 
    }
}
#endif
Имеется класс-наследник в derived.h:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#ifndef DERIVED_H
#define DERIVED_H
 
 
 
#include"Base.h"
#include <boost/serialization/base_object.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/export.hpp>
 
 
class derived : public Base{
   private:
      friend class boost::serialization::access;
      template <typename Archive>
      void serialize(Archive& ar, const unsigned version) {
               ar & boost::serialization::base_object<Base>(*this);
      }
   public:
       //constructor
    derived (int a, int b):Base(a,b,3) {};
    
        //virtual function from the base class
    int getN() {return 1;};
 
 
};
 
#endif
И все это выполняется в main.cpp:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include<fstream>
#include<iostream>
#include"derived.h"
#include"Base.h"
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
 
 
int main(){
   //Initialize some variables
   int a = 3, b = 4;
   //input and output files
   std::ofstream ofs("output.txt");
   std::ifstream ifs("output.txt");
    
   //new object of <derived> type 
   Base *A = new derived(a,b);
   
   //save the A
   {
    boost::archive::text_oarchive oa(ofs);
    // write class instance to archive
    oa << A;
    // archive and stream closed when destructors are called
        std::cout<<"DONE WRITING";
   }
   
   //что делать тут? добавлять констурктор по умолчанию в derived, чтобы это выглядело так? а потом подгружать данные из архива
   Base *B = new derived();
   {
    boost::archive::text_iarchive ia(ifs);
    // write class instance to archive
    ia >> B;
    // archive and stream closed when destructors are called
        std::cout<<"DONE READING";
   }
 
 
 
}
и вот теперь главные вопросы:
  1. Нужно ли переписывать load_construct_data и save_construct_data для базового типа как показано в примере кода, или это делать в наследнике?
  2. Какой объект создавать в load_construct_data: Base (по идее создать не получится, так как это виртуальный класс, но нам же как то нужно сериализовать этот тип) или derived (перенеся функцию load в соотеветствующий файл)?
  3. При чтение из архива какой объект создавать и как?
  4. ну и в общем...верна ли данная идея сериализации?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
20.03.2013, 20:10
Ответы с готовыми решениями:

Указатель на абстрактный шаблонный класс
Есть абстрактный шаблон класса и 3 производных от него шаблонов классов. Так же...

Абстрактный класс без виртуальных функций
Мне нужен класс без виртуальных функций, но чтобы его нельзя было создать....

Создание объекта через указатель на базовый абстрактный класс
Есть абстрактный класс, от него наследуется 3 класса. В программе предусмотрено...

Не имеющий конструктора без параметров базовый класс (аргументов) не разрешает плодить наследников
Здравствуйте, никак не могу понять, в чём проблема. Возникла необходимость...

Класс: Создать абстрактный базовый класс Figure с виртуальными методами вычисления площади и периметра.
Создать абстрактный базовый класс Figure с виртуальными методами вычисления...

8
ForEveR
В астрале
Эксперт С++
7995 / 4754 / 651
Регистрация: 24.06.2010
Сообщений: 10,547
Завершенные тесты: 3
22.03.2013, 13:08 #2
А зачем создавать базовый? По идее как раз load/save для базового не играют ровно никакой роли. Потому load/save data для Derived-ов и все. + регистрация в архиве derived классов. Таким образом получается

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#include <boost/serialization/serialization.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/shared_ptr.hpp>
 
#include <sstream>
 
namespace serialization = boost::serialization;
namespace archive = boost::archive;
 
class Base
{
   friend class boost::serialization::access;
   template<typename Archive>
   void serialize(Archive& ar, const unsigned int)
   {
      ar & f;
   }
public:
   Base(int i) : n(i), f(0) {}
   virtual ~Base() = 0;
   int n;
   int get() const { return f; }
private:
   int f;
};
 
Base::~Base() {}
 
class Derived : public Base
{
   friend class boost::serialization::access;
   template<typename Archive>
   void serialize(Archive& ar, const unsigned int)
   {
      ar & boost::serialization::base_object<Base>(*this);
   }
public:
   Derived(int n, int t) : Base(n), z(t) {}
   int z;
};
 
class Derived2 : public Base
{
   friend class boost::serialization::access;
   template<typename Archive>
   void serialize(Archive& ar, const unsigned int)
   {
      ar & boost::serialization::base_object<Base>(*this);
   }
public:
   Derived2(int n) : Base(n) {}
};
 
namespace boost { namespace serialization {
template<typename Archive>
inline void save_construct_data(Archive& ar, const Derived* b, const unsigned int)
{
   ar << b->n;
   ar << b->z;
}
 
template<typename Archive>
inline void load_construct_data(Archive& ar, Derived* b, const unsigned int)
{
   int n = 0, z = 0;
   ar >> n;
   ar >> z;
   ::new(b) Derived(n, z);
}
 
template<typename Archive>
inline void save_construct_data(Archive& ar, const Derived2* b, const unsigned int)
{
   ar << b->n;
}
 
template<typename Archive>
inline void load_construct_data(Archive& ar, Derived2* b, const unsigned int)
{
   int n = 0;
   ar >> n;
   ::new(b) Derived2(n);
}
 
}}
 
int main()
{
   {
   std::stringstream ss;
   archive::text_oarchive oarch(ss);
   oarch.register_type<Derived>();
   Base* b = new Derived(1, 5);
   oarch << b;
   delete b;
   Derived* ptr;
   archive::text_iarchive iarch(ss);
   iarch >> ptr;
   std::cout << ptr->n << " " << ptr->z << " " << ptr->get() << std::endl;
   delete ptr;
   }
   {
   std::stringstream ss;
   archive::text_oarchive oarch(ss);
   oarch.register_type<Derived2>();
   Base* b = new Derived2(10);
   oarch << b;
   delete b;
   Derived2* ptr2;
   archive::text_iarchive iarch(ss);
   iarch >> ptr2;
   std::cout << ptr2->n << " " << ptr2->get() << std::endl;
   delete ptr2;
   }
}
С выделением памяти при сериализации в указатель заморачиться не нужно, судя по всему буст корректно выделяет память через
C++
1
operator new(size_t)
1
sl_k
12 / 12 / 4
Регистрация: 15.04.2010
Сообщений: 61
22.03.2013, 13:29  [ТС] #3
Спасибо.
А если мы немного модифицируем Base, так что для конструктора нам надо будет вторую переменную записать в private f. Тогда f надо будет все равно записывать через Base, или и в Base, и в save_cunstuct_data через геттер для derived2?

C++
1
2
3
4
5
6
7
8
9
10
11
12
class Base { 
     friend class boost::serialization::access; 
     
     template<typename Archive> void serialize(Archive& ar, const unsigned int) 
    { ar & f; } 
     public: 
         Base(int i, int j) : n(i), f(j) {} 
         virtual ~Base() = 0; int n; 
         int get() const { return f; } 
     private: 
          int f; 
  };

и соответственно

C++
1
2
3
4
5
6
7
8
9
10
11
class Derived2 : public Base
{
   friend class boost::serialization::access;
   template<typename Archive>
   void serialize(Archive& ar, const unsigned int)
   {
      ar & boost::serialization::base_object<Base>(*this);
   }
public:
   Derived2(int n, int f) : Base(n, f) {}
};

тогда для того чтобы сохранить derived2, нам надо будет уже использовать геттер для f?

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
template<typename Archive>
inline void save_construct_data(Archive& ar, const Derived2* b, const unsigned int)
{
   ar << b->n;
   ar << b->get();
}
 
template<typename Archive>
inline void load_construct_data(Archive& ar, Derived2* b, const unsigned int)
{
   int n = 0;
   int f = 0;
   ar >> n;
   ar >> f;
 
   ::new(b) Derived2(n,f);
}
я правильно понял?
0
ForEveR
В астрале
Эксперт С++
7995 / 4754 / 651
Регистрация: 24.06.2010
Сообщений: 10,547
Завершенные тесты: 3
22.03.2013, 13:50 #4
sl_k, В load_construct_data точно. И в save очевидно тоже. Как-то ведь сконструировать объект надо
0
sl_k
12 / 12 / 4
Регистрация: 15.04.2010
Сообщений: 61
22.03.2013, 16:58  [ТС] #5
ForEveR, Это то да, но тогда в derived2 save_construct_data мы записываем f через get(), и в добавок еще в базовом классе в процедуре serialize. не запишется ли f дважды таким образом?
0
ForEveR
В астрале
Эксперт С++
7995 / 4754 / 651
Регистрация: 24.06.2010
Сообщений: 10,547
Завершенные тесты: 3
22.03.2013, 18:26 #6
sl_k, Что-то мне подсказывает, что в базовом классе эту функцию стоит оставить пустой.
1
sl_k
12 / 12 / 4
Регистрация: 15.04.2010
Сообщений: 61
22.03.2013, 19:14  [ТС] #7
ForEveR, не хочет компилятор со мной по хорошему работать, даже если save_construct_data друг для Derived2 и get() - public у Base:

Bash
1
2
3
4
5
In function ‘void boost::serialization::save_construct_data(Archive&, const Derived2*, unsigned int)’:
error: no matching function for call to ‘Derived2::get() const’
note: candidate is:
const int Base::get() <near match>
no known conversion for implicit ‘this’ parameter from ‘const Derived2*’ to ‘Base*
0
ForEveR
В астрале
Эксперт С++
7995 / 4754 / 651
Регистрация: 24.06.2010
Сообщений: 10,547
Завершенные тесты: 3
22.03.2013, 19:16 #8
sl_k, Ну резонно же. Почему get функция не константная?
1
sl_k
12 / 12 / 4
Регистрация: 15.04.2010
Сообщений: 61
22.03.2013, 19:43  [ТС] #9
Добавлено через 3 минуты
Ну и финильная модификация save для переменной f, и компилятор приветствует меня завершением сборки

C++
1
2
3
4
5
6
7
8
template<typename Archive>
inline void save_construct_data(Archive& ar, const Derived2* b, const unsigned int)
{
   ar << b->n;
   int f;
   f = b->get();
   ar << f;
}
0
22.03.2013, 19:43
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
22.03.2013, 19:43

Абстрактный базовый класс
Привет всем! У меня есть абстрактный базовый класс Object.Он содержит различные...

Абстрактный базовый класс
Создать абстрактный базовый класс с виртуальной функцией - объем. Создать...

абстрактный базовый класс
люди подскажите.есть абстрактный базовый класс можно ли в нем определить...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
9
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru