crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

 
Ответить в данную темуНачать новую тему
> Ошибка при работе с boost::any
AD
  опции профиля:
сообщение 9.8.2009, 21:12
Сообщение #1


Профессионал
*****

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

Спасибо сказали: 70 раз(а)




Репутация:   17  


Почему-то вылетает с ошибкой при работе со следующим кодом:
void fillVectorTypes(std::vector<any>& types)
{
    DCW_HEAD type_1;            HEAD type_2;
    types.push_back(type_1);    types.push_back(type_2);
}

/// Инициализация заголовка карты и ее флагов
void CategoriesCharts::initMapEntity(const TabType key, MapEntity& entity)
{
    QFile file(entity.name());
    if(!file.open(QIODevice::ReadOnly)) return;
    qint64 sz = -1;
    std::vector<any> _types;
    fillVectorTypes(_types);
    file.read((char*)&_types[key], sizeof(_types[key]));
    file.close();
}


Правда, структуры не имеют конструкторов, но это код библиотеки:
struct DCW_HEAD
{
  char  title [16],
        File_name [8];
  float Latb, Late,
        Lonb, Lone,
        C0;
};

typedef unsigned char UByte;
typedef signed   char SByte;

struct HEAD
{
  char  title [TRS_TITLE_LEN],
        Corr_date [11],
        Chart_name [9],
        File_name  [9];
  float dlat, dlon,
        Latb, Late,
        Lonb, Lone,
        Latm, C0;
  short year_PD, month_PD,
        year_PP, month_PP,
        year_EC, month_EC;
  char  WGS;
  SByte  DP_mean,
        LH_dir,
        Datum,
        Proj,
        Type,
        Cntr,
        LangP,
        LangE,
        Reg,
        CntG,
        compress;

  SByte  WaterLevel,
        HO_mean,
        TypeEx;

  SByte  PubNum;
  SByte  CorrIssue;

  SByte  reserved [ 2 ];
  SByte  revision;
};


Отладчик выпадает на следующие строки:
~any()
        {
            delete content;
        }

Как можно исправить ошибку?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
BRE
  опции профиля:
сообщение 10.8.2009, 7:59
Сообщение #2


Профессионал
*****

Группа: Участник
Сообщений: 1112
Регистрация: 6.3.2009
Из: Ростов-на-Дону
Пользователь №: 591

Спасибо сказали: 264 раз(а)




Репутация:   44  


sizeof( any ) == 4, т.е. он хранит указатель на внутренний объект (content)!
Читая file.read((char*)&_types[key], sizeof(_types[key])) ты этот указатель затираешь первыми четырьмя байтами из файла. При разрушении any программа падает. Все логично. ;)
Обрати внимание на any_cast<Type>(...)!!!
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
AD
  опции профиля:
сообщение 10.8.2009, 8:12
Сообщение #3


Профессионал
*****

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

Спасибо сказали: 70 раз(а)




Репутация:   17  


Цитата
sizeof( any ) == 4, т.е. он хранит указатель на внутренний объект (content)!
Читая file.read((char*)&_types[key], sizeof(_types[key])) ты этот указатель затираешь первыми четырьмя байтами из файла. При разрушении any программа падает. Все логично. ;)
Обрати внимание на any_cast<Type>(...)!!!

А как именно поправить я не понял? Прости, если донимаю...
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
BRE
  опции профиля:
сообщение 10.8.2009, 8:20
Сообщение #4


Профессионал
*****

Группа: Участник
Сообщений: 1112
Регистрация: 6.3.2009
Из: Ростов-на-Дону
Пользователь №: 591

Спасибо сказали: 264 раз(а)




Репутация:   44  


Цитата(AD @ 10.8.2009, 9:12) *
А как именно поправить я не понял? Прости, если донимаю...

Примерно так:
void CategoriesCharts::initMapEntity(const TabType key, MapEntity& entity)
{
    QFile file(entity.name());
    if(!file.open(QIODevice::ReadOnly)) return;
    qint64 sz = -1;
    std::vector<any> _types;
    fillVectorTypes(_types);
    if( _types[ key ].type() == typeid( DCW_HEAD ) )
        file.read( (char*)&any_cast<DCW_HEAD>( _types[ key ] ), sizeof( any_cast<DCW_HEAD>( _types[key] ) ) );
    else if( _types[ key ].type() == typeid( HEAD ) )
        file.read( (char*)&any_cast<HEAD>( _types[ key ] ), sizeof( any_cast<HEAD>( _types[key] ) ) );
    file.close();
}
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
AD
  опции профиля:
сообщение 11.8.2009, 8:26
Сообщение #5


Профессионал
*****

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

Спасибо сказали: 70 раз(а)




Репутация:   17  


Цитата(BRE @ 10.8.2009, 9:20) *
Примерно так:

Спасибо. А вопрос такой, а можно ли это сделать так, чтобы при добавлении, например, еще какого-то типа данных, ну например топографии другого формата, не надо было бы еще одну ветку else делать? Т.е. смысл-то этого вектора с any, чтобы он автоматом определял тип, а не при непосредственном приведении.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
BRE
  опции профиля:
сообщение 11.8.2009, 12:17
Сообщение #6


Профессионал
*****

Группа: Участник
Сообщений: 1112
Регистрация: 6.3.2009
Из: Ростов-на-Дону
Пользователь №: 591

Спасибо сказали: 264 раз(а)




Репутация:   44  


Цитата(AD @ 11.8.2009, 9:26) *
Цитата(BRE @ 10.8.2009, 9:20) *
Примерно так:

Спасибо. А вопрос такой, а можно ли это сделать так, чтобы при добавлении, например, еще какого-то типа данных, ну например топографии другого формата, не надо было бы еще одну ветку else делать? Т.е. смысл-то этого вектора с any, чтобы он автоматом определял тип, а не при непосредственном приведении.

Поэтому я тебе и написал, что не могу понять для чего ты все это делаешь. Теперь понял. ;)

IMHO any не очень подходит для таких задач. Можно попробовать получать имя типа из type_info, но все равно придется городить свой if для каждого типа. При добовлении нового типа, нужно будет дописывать свою ветвь.

Может лучше воспользоваться фабриками. Для каждого типа карты делается специальный класс loader, который умеет ее загружать. Все они регистрируются в фабрике и она создает объект-загрузчик в зависимости от указанного типа.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
AD
  опции профиля:
сообщение 11.8.2009, 12:22
Сообщение #7


Профессионал
*****

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

Спасибо сказали: 70 раз(а)




Репутация:   17  


Цитата(BRE @ 11.8.2009, 13:17) *
Поэтому я тебе и написал, что не могу понять для чего ты все это делаешь. Теперь понял. ;)

IMHO any не очень подходит для таких задач. Можно попробовать получать имя типа из type_info, но все равно придется городить свой if для каждого типа. При добовлении нового типа, нужно будет дописывать свою ветвь.

Может лучше воспользоваться фабриками. Для каждого типа карты делается специальный класс loader, который умеет ее загружать. Все они регистрируются в фабрике и она создает объект-загрузчик в зависимости от указанного типа.

Об этом подумал. Какой класс буста использовать? :) Как приблизительно это можно реализовать? Спасибо за помощь!!!
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
BRE
  опции профиля:
сообщение 11.8.2009, 18:14
Сообщение #8


Профессионал
*****

Группа: Участник
Сообщений: 1112
Регистрация: 6.3.2009
Из: Ростов-на-Дону
Пользователь №: 591

Спасибо сказали: 264 раз(а)




Репутация:   44  


Цитата(AD @ 11.8.2009, 13:22) *
Об этом подумал. Какой класс буста использовать? :) Как приблизительно это можно реализовать? Спасибо за помощь!!!

Мне понравилось одно решение с фабриками (подсмотрел на Inside C++). Я его немного переделал, что бы в качестве ключа можно было использовать не только строки.
Раскрывающийся текст

template <typename key, class base>
class factory
{
public:

    typedef boost::shared_ptr<base> base_ptr;

    template <class derived>
    void reg( const key& name )
    {
        factories[ name ] = base_type_ptr( new derived_type<derived> );
    }

    base_ptr create( const key& name )
    {
        if( !factories.count( name ) )
            throw std::out_of_range( "factory: key not found" );
        return factories[ name ]->create();
    }

private:

    class base_type
    {
    public:

        virtual ~base_type() {}

        virtual base_ptr create() const = 0;
    };

    typedef boost::shared_ptr<base_type> base_type_ptr;

    template <class T>
    class derived_type : public base_type
    {
    public:

        virtual base_ptr create() const
        {
            return base_ptr( new T );
        }
    };

    typedef std::map<key, base_type_ptr> factory_container;
    factory_container factories;
};



Как это использовать:
Раскрывающийся текст

// Виртуальный базовый класс
class Loader
{
public:
    virtual    bool load() = 0;
};

// Загружает карту земли
class EarthMapLoader : public Loader
{
public:
    virtual    bool load();
};

// Загружает карту моря
class SeaMapLoader : public Loader
{
public:
    virtual    bool load();
};

void func()
{
    typedef factory<int, Loader> LoaderFactory;
    typedef LoaderFactory::base_ptr LoaderPtr;

    LoaderFactory loaders;

    // Регистрируем загрузчики
    loaders.reg<EarthMapLoader>( 0 );
    loaders.reg<SeaMapLoader>( 1 );

    // Использование
    int index = 1;        // index тип карты
    
    // В зависимости от index создаем нужный объект загрузчика
    LoaderPtr loader = loaders.create( index );

    // loader - указывает на объект SeaMapLoader
    // Вызываем метод load
    loader->load();
}



Сообщение отредактировал BRE - 11.8.2009, 19:07
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


3 чел. читают эту тему (гостей: 3, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 22.11.2024, 15:45