Ошибка: невозможно dynamic_cast ... (цель не указатель или ссылка)

Я изучаю обработку исключений в C++ и столкнулся с проблемой. Вот код:

#include<iostream>
#include<exception>

using namespace std;

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

class AA:public A
{
public:
    void aa(void){};

};

int main(void)
{

    A a;
    try
    {
        dynamic_cast<AA>(a).aa();
    }
    catch(exception ex)
    {
        cout<<"["<<ex.what()<<"]"<<endl;
    }
    return 0;
}

Поэтому я подумал, что try catch позволит функции выполняться и покажет мне содержимое исключения, но мой компилятор не компилирует его. Я использую кодовый блок с GNU GCC. Пожалуйста, помогите мне и покажите, что мне нужно сделать, чтобы код работал так, как я планировал. большое спасибо.

4 ответа

dynamic_cast может привести только к значению указателя или ссылке, что именно то, что говорит вам ошибка.

От $5.2.7/1 стандарта C++.

Результатом выражения dynamic_cast (v) является результат преобразования выражения v в тип T. T должен быть указателем или ссылкой на полный тип класса или "указателем на cv void".

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

dynamic_cast<AA&>(a).aa();
//           ^^^ cast to reference.

Как указал Johnsyweb dynamic_cast всегда будет бросать std::bad_cast когда преобразование не удается. Хотя std::bad_cast происходит от std::exception всегда полезно использовать исключение, которое наилучшим образом соответствует ожидаемому условию сбоя. Это предотвращает непреднамеренную интерпретацию других ошибок как неудачного приведения.

Чтобы применить это к вашему примеру, это может выглядеть как код ниже.

#include <iostream>
#include <typeinfo> // std::bad_cast

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

class AA:public A
{
public:
    void aa(void){};
};

int main(void)
{
    A a;

    try
    {
        dynamic_cast<AA&>(a).aa();
    }
    catch(const std::bad_cast& ex)
    {
        std::cout << "["<<ex.what()<<"]" << std::endl;
    }
    return 0;
}

[Примечание, делать такие вещи, как using namespace std; Настоятельно не рекомендуется, так как это может вызвать конфликты с идентификаторами в глобальном пространстве имен. Я удалил это в примере выше.]

Ваша проблема не в обработке исключений, а в динамическом приведении:

'AA' is not a reference or pointer

dynamic_cast безопасно конвертирует указатели и ссылки на class а не экземпляры.

Так что вы могли бы сделать:

dynamic_cast<AA&>(a).aa();

... который всегда потерпит неудачу и бросит std::bad_cast исключение.

Вы должны поймать наиболее специфический тип exception что вы ожидаете и так как рекомендуемый способ catch По ссылке, вы должны предпочесть:

catch (std::bad_cast const& ex)

Дополнительная информация: преобразование dynamic_cast на http://en.cppreference.com/.

Я просто имел дело с той же ошибкой, но в моем случае я переходил от указателя к указателю, поэтому другие ответы здесь не применимы. Мое сообщение об ошибке немного отличалось: error: cannot dynamic_cast 'f()' (of type 'class B*') to type 'class A*' (target is not pointer or reference to complete type),

Основная причина в моем случае была гораздо более простой и обыденной.

Обратите внимание на добавление завершить тип в конце. Это заставило меня вспомнить, что я не включил заголовочный файл для своего класса, который я использовал. Это был не неизвестный символ, потому что A* был вперед объявлен с class A; в заголовочном файле, в результате чего он существует, но не является полным, отсюда и ошибка.

Решение в моем случае состояло в том, чтобы включить файл заголовка для класса, к которому я приводил.

Это не проблема вопроса, которая была задана выше, но, как видно из моего случая, может генерировать ошибку такого же типа.

Вы получаете ошибку компилятора, потому что ваш dynamic_cast не указатель или ссылка.
Измените это на:

dynamic_cast<AA&>(a).aa();

... и вы получите правильное исключение.

Примечание: умные компиляторы, такие как g++, также предупреждают:
предупреждение: dynamic_cast на объекте (здесь a ) никогда не сможет добиться успеха.

Так что лучше ограничить такой код для игры. В коде качества продукции dynamic_cast должно выполняться только по указателю / ссылке.

Другие вопросы по тегам