Используя виртуальную функцию в ребенке после кастинга операции в C++

У меня есть следующий код:

class A
{
};

class B : public A
{
    public:
        virtual void f() {}
};

int main()
{
    A* a = new A();
    B* b = static_cast<B*>(a);
    b->f();
}

Эта программа перестала работать с отказом сегментации. Существует два решения заставить эту программу работать:

  1. объявите f невиртуальный
  2. не называйте b-> f () (т.е. он перестал работать не из-за броска),

Однако оба не опция. Я предполагаю, что это не работает из-за поиска в vtable.

(В реальной программе A действительно также имеет виртуальные функции. Кроме того, виртуальная функция не вызвана в конструкторе.)

Существует ли способ заставить эту программу работать?

7
задан John Dibling 9 February 2010 в 16:16
поделиться

4 ответа

You can't do that because the object you create is A, not B. Your cast is invalid-- an object of A (created with new) cannot magically become an object of B.

Did you mean the A* a = new A() to actually be A* a = new B()? In that case, I would expect it to work.

12
ответ дан 6 December 2019 в 09:19
поделиться

Вы не можете этого сделать.

В вашем примере a является объектом класса A. Не B. Приведение его к B не делает его B.

Если вы хотите использовать поведение полиморфного объекта, вы можете передать виртуальную функцию f классу A, и вы можете использовать код вроде A * a = new B (); Затем вы можете использовать виртуальные функции через указатель, чтобы получить поведение из класса B.

3
ответ дан 6 December 2019 в 09:19
поделиться

Вы не можете сделать это, потому что объект, который вы создаете, является A, а не B. Ваш состав недействителен - объект A (созданный с новым) не может магически стать объектом B.

Вы имели в виду, что A * a = new A () на самом деле является A * a = new B ()? В таком случае я бы ожидал, что это сработает.

-121--3823376-

Как для Linux, так и для FreeBSD вы можете попробовать работать через выход ldconfig (8) . Однако варианты перечисления библиотек различны ( -p в Linux , -r в FreeBSD .) Надеюсь, это поможет.

Изменить:

Solaris отличается - см. man crle .
Mac OSX снова отличается - см. man dyld .

-121--4012985-

Для выполнения static _ cast необходимо убедиться, что объект может быть отлит , т.е. является объектом класса B .

В данном случае я уверен, что это не .

2
ответ дан 6 December 2019 в 09:19
поделиться

В вашем коде:

    A* a = new A();

Вы инстанцируете объект A. Затем вы пытаетесь использовать static_cast для перехода от базового типа к производному:

B* b = static_cast<B*>(a);

Если бы значение в a указывало на объект, который действительно имеет тип B, это было бы законно и хорошо сформировано. Но a не указывает на объект типа B, а указывает на A, поэтому приведение вызывает неопределенное поведение.

Исправление заключается в изменении способа инстанцирования объекта. Изменить:

A* a = new A();

...на:

A* a = new B();
3
ответ дан 6 December 2019 в 09:19
поделиться
Другие вопросы по тегам:

Похожие вопросы: