2016-11-07 1 views
-2

Я прошу об этом, потому что даже, похоже, это работает, я чувствую, что это не должно. Цель состоит в том, чтобы иметь коллекцию объектов, находящихся в живых, и общий доступ к ним. Это то, что я имею на данный момент:Является ли объект действительным в сериализованной форме? C++/наследование/сериализация

Сделайте доступ базового указателя:

struct base { virtual void tick() = 0; }; //ptr access 

с различными типами, которые наследуют от него:

struct :public base 
{ 
    void tick() { cout << "im type 1" << endl; } 
}type1; 

struct :public base 
{ 
    void tick() { cout << "im type 2" << endl; } 
}type2; 

Тогда класс контейнера, который должен быть в состоянии хранить любое количество этих сериализованная:

class control 
{ 
    struct xtype //struct for organizing objects 
    { 
     vector<char>charbuf; //serialized object 
    }xtype_template; 

    vector<xtype>xtype_vec; 

public: 

    template<typename T> base* tell_to(T &input) //take object, return (base*) 
    { 
     xtype_template.charbuf.resize(sizeof(input)); 
     memcpy(xtype_template.charbuf.data(), (char*)&input, sizeof(input)); 

     xtype_vec.push_back(xtype_template); //push back with template after filling 

     return (base*)xtype_vec[xtype_vec.size() - 1].charbuf.data(); //pointer to data 
    } 
}xcontainer; //container object 

Тогда звоните:

auto ptr = controller.tell_to(type1); //becomes base* 
auto ptr2 = controller.tell_to(type2); 

И вы можете получить доступ к любому статическому размерному сериализованному объекту, а также его состояния, выполнив:

ptr->tick(); //which will output "im type 1" to console 
ptr2->tick() //"im type 2" 

Но это законно? Имеют ли эти сериализованные версии фактический тип? Является ли доступ к сериализованному объекту напрямую с базовым указателем незаконным или неправильным?


Ближайший вероятный ответ: как возвращение на is_trivially_copyable показать ложные, объекты не могут быть безопасно управлять после получения базового наследования.

Последующий подход: этот подход, похоже, работает, и возиться с is_trivially_copyable, кажется, предполагает, что создание объекта наследует методы, делает его небезопасным. Однако основные методы не делают его небезопасным, и это заставляет меня задаться вопросом, распространяется ли безопасность только на экспорт между системами, сохранение в файл или передачу по сети. Может быть, проверка просто предполагает, что виртуальная ссылка делает их небезопасными?

Последующие действия 2: Если символы остаются в одном и том же месте в памяти, имеет ли значение, как они доступны? Id заявляет, что единственная реальная проблема с этим подходом заключается в том, что если хранящиеся объекты должны иметь элементы, которые изменили бы их размер после их сохранения.

+0

Я хочу иметь коллекцию различных объектов в векторе (векторов). Идея состоит в том, чтобы хранить объекты-объекты, которые указывают контейнеру, что должен делать tick(), или обобщать доступ к методам между типами, если это имеет смысл – Charlie

+0

как вектор > objs_owner; ? hm Я не думаю, что я знаком с этим подходом. Он не будет обрезать объекты? – Charlie

+0

См. Мой ответ, мой оригинальный комментарий был неправильным. – SergeyA

ответ

6

Что вы делаете, является незаконным. Вы можете только memcpy объект в качестве массива char с, когда объект TriviallyCopyable. И ваш объект не является, поскольку он имеет виртуальные функции.

Вместо этого вы должны просто сохранить (уникальный) указатель на вновь выделенный объект и избежать любых приведений для обеспечения иерархии. Как это:

class xtype 
{ 
    std::unique_ptr<base> ptr; 

public: 

    template<typename T> base* serial_acc(T &input) //take object, return (base*) 
    { 
     static_assert(std::is_base_of<base, T>::value, "Please use proper type"); 
     ptr = std::make_unique<base>(input); 
     return ptr; 
    } 
} xcontainer; 
+0

Также, помимо 'TriviallyCopyable', вы можете отбрасывать символ' char 'обратно указателю на объект, если' char 'правильно выровнены для типа (иначе вам нужно скопировать их обратно в выровненное хранилище). –

+0

@ AndréSassi, в то время как в целом правильный, выравнивание - это реализация, а основные реализации на основных платформах поддерживают неравномерный доступ. – SergeyA

+0

Я все еще не убежден, что это небезопасно для того, что я пытаюсь сделать. Это может быть опасно для сетей и экспорта в файлы, но в частном порядке, как это? @SergeyA – Charlie

1

Рабочий пример задается пользователем Andy Prowl

#include <vector> 
#include <memory> 
#include <iostream> 
using namespace std; 

struct base 
{ 
    virtual void tick() = 0; 
}; 

struct type1 : base 
{ 
    virtual void tick() override { cout << "im type 1"<<endl; } 
}; 

struct type2 : base 
{ 
    virtual void tick() override { cout << "im type 2" << endl; } 
}; 

struct controller 
{ 
    vector<unique_ptr<base>> objects; 

    void cycle_tick(){ for (auto const& ptr : objects)ptr->tick();} 

    void add_object(unique_ptr<base> obj){ objects.emplace_back(move(obj));} 

}; 

int main() 
{ 
    auto t1 = unique_ptr<type1>(new type1); 
    auto t2 = unique_ptr<type2>(new type2); 

    controller ctrl_object; 
    c.add_object(move(t1)); 
    c.add_object(move(t2)); 

    ctrl_object.cycle(); 
} 
Смежные вопросы