Ловля исключений полиморфно - PullRequest
3 голосов
/ 03 августа 2009

Вот main():

int main()
{
    B b(1,"two","three");
    try
    {
        f1(b);
    }
    catch(B& b_ref)
    {
        cout<<"Caught B&"<<endl;
        b_ref.print();
    }
    catch(A& a_ref)
    {
        cout<<"Caught A&"<<endl;
        a_ref.print();
    }

    system("pause");
    return 0;
}

Вот f1():

void f1(A& subject)
{
    throw subject;
}    

Информация:

B наследуется от A. A::print() является виртуальным и переопределено в B. Вылов, который ловит исключение, catch(A& a_ref), что, я думаю, имеет смысл, поскольку статический тип (субъект) исключений - A &. НО, почему не работает B:: print()? Динамический тип "потерян"? Только A::print() работает в строке a_ref.print();.

Может кто-нибудь объяснить?

Ответы [ 6 ]

6 голосов
/ 03 августа 2009

Согласно стандарту C ++ 15.1 / 3:

Выражение throw инициализирует временный объект, называемый объектом исключения, тип которого определяется путем удаления любых cv-квалификаторов верхнего уровня из статического типа операнда throw ...

Итак, вы создаете временный объект типа A, а не B.

6 голосов
/ 03 августа 2009

throw только выбрасывает объект типа выражения, следующего за ним. В этом случае subject имеет тип A&, независимо от того, что является фактическим объектом, поэтому A выдается (обратите внимание, что ссылки не могут быть выброшены, поэтому создается копия).

Вы можете справиться с этим, добавив функцию-член к вашим классам исключений, которая выдает исключение. Пока вы реализуете этот метод в каждом классе, вызываемое переопределение будет знать тип времени выполнения объекта и может throw *this.

http://www.ddj.com/cpp/184401940

5 голосов
/ 03 августа 2009

Когда вы говорите «throw subject», создается новый объект исключения на основе статического типа выражения броска (subject). Тот факт, что subject является ссылкой, не имеет значения для определения того, какой объект бросить. Новый объект A является копией, созданной из subject. Эта копия (или, возможно, копия этой копии) является фактическим объектом, который пойман.

4 голосов
/ 03 августа 2009

Блоки Catch работают полиморфно, а бросок - нет. Когда вы говорите:

void f1(A& subject)
{
    throw subject;
}

вы бросаете A, хотя переданная функции функция - B.

0 голосов
/ 03 августа 2009

Н.В.М., мой недостаток навыков понимания прочитанного. Мысль он создает объекты типа А.

0 голосов
/ 03 августа 2009

Поскольку вы ловите по ссылке, объект «нарезан».

Если вы действительно хотите полиморфного поведения, попробуйте использовать что-то вроде идиомы pimpl.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...