Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

C++ Не могу понять что происходит

59K
18 августа 2012 года
SANRIZE
16 / / 06.04.2011
Во общем есть такой кусок кода:

Код:
class AA
{
    public:
    virtual ~AA()
    {
    }
    protected:
    virtual int Foo(int id) = 0;
};

class BB:public AA
{
    public:
    BB()
    {
       
    }
    virtual ~BB()
    {
    }
    virtual int Foo(int id)
    {
        return 0;
    }
    private:        //если их убрать заработает
    int* Top_;
    int  Lop_;
};
//а теперь использование

    BB uu;
    uu.Foo(32);         //Все ок в люб случае

    AA *arr = new BB[16];
    BB &b = *((BB*)&arr[2]);

    int val = b.Foo(32);        //вылет в том случае если есть переменные Top Lop
Кто может объяснить почему происходит вылет!
414
18 августа 2012 года
CassandraDied
763 / / 24.05.2012
Потому что ты сделал что-то нехорошее с кастами. В итоге b перестаёт являться валидным объектом, поэтому и не вызвать метод.
Смотри отладчиком, какие поля неверное копируются при преобразовании.
59K
18 августа 2012 года
SANRIZE
16 / / 06.04.2011
Если дописать в класс BB новый метод, не вирт, он нормально отработает тут не в валидности тут нечто иное!
414
18 августа 2012 года
CassandraDied
763 / / 24.05.2012
Ага. А если
 
Код:
AA *arr = new BB[16];
Поменять на
 
Код:
BB *arr = new BB[16];
То будет работать с любым количеством методов и полей.

Код:
class BB:public AA
{
     public:
     BB()
     {
        Top_ = (int*)0x1;
        Lop_ = 2;
     }
     virtual ~BB()
     {
     }
     virtual int Foo(int id)
     {
         return 0;
     }
     private:        //если их убрать заработает
     int* Top_;
     int  Lop_;
};
59K
18 августа 2012 года
SANRIZE
16 / / 06.04.2011
Не! Замен нельзя никаких делать. Должен именно быть базовый класс АА.
414
19 августа 2012 года
CassandraDied
763 / / 24.05.2012
Ты спрашивал, почему происходит вылет и ничего не писал про то, как должно быть и что тебе вообще нужно.
260
19 августа 2012 года
Ramon
1.1K / / 16.08.2003
 
Код:
AA *arr = new BB[16];
BB &b = *((BB*)&arr[2]);
И на размер чего, по вашему, будет опираться компилятор при попытке получить элемент №2 в массиве? А что там на самом деле?
85K
19 августа 2012 года
Wrapper
2 / / 17.08.2012
Приведение указателей на объекты в стиле C - плохо, потому что неявно. Лучше в данном примере вызывать dynamic_cast явно.

Тогда станет понятно, в чем причина. Компилятор пытается привести массив BB к массиву AA через RTTI, но это невозможно, поскольку тип массива BB не унаследован от типа массива AA. В результате генерируется исключение __non_rtti_object.

Решение - использовать контейнер, например std::vector. Он проведет четкую грань между массивом и указателем на объект.

Следующий код у меня работает:


 
Код:
std::vector<AA*> test;

for (size_t i=0; i<16; i++)
   test.push_back(new BB());
   
BB *b = dynamic_cast<BB*>(test[2]);

std::cout << b->Foo(0) << std::endl;
Данный пример имеет потенциальную утечку памяти, но сделано это ради простоты кода. В реальном коде перед удалением объекта vector нужно либо вручную пройтись по элементам и вызвать delete, либо использовать умные указатели.
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог