Ошибка определения ошибки Looser в С++
Следующий код генерирует ошибку "Ошибка определения маркера Looser". Не могли бы вы помочь мне преодолеть эту ошибку?
class base
{
virtual void abc() throw (exp1);
}
void base::abc() throw (exp1)
{
......
}
class sub : public base
{
void abc() throw(exp1, exp2);
}
void sub::abc() throw (exp1, exp2)
{
.....
}
Ответы
Ответ 1
Проблема возникает из-за того, что подкласс должен использоваться везде, где может использоваться базовый класс, и поэтому не должен генерировать типы исключений, отличные от тех, которые указаны в базовом классе.
Существует три решения:
- Измените спецификатор базового класса, чтобы включить каждый тип исключения, который может понадобиться любому подклассу
- Изменить каждый подкласс для обработки каждого типа исключения, кроме тех, которые указаны в базовом классе
- Удалить спецификаторы исключений.
Я бы предложил их удалить; они широко расцениваются как плохая идея, отчасти из-за таких проблем. Как указывает Маттиу, стандарт согласен, и спецификаторы исключений должны быть устаревшими в следующей версии Стандарта.
Ответ 2
Когда вы переопределяете виртуальный метод с помощью спецификатора throw в производном классе, метод в производном классе не может вызывать больше исключений, чем метод в суперклассе. Если вам разрешили это сделать, вы можете разорвать контракт, созданный публичным API суперкласса, переопределив методы в подклассе.
В вашем примере вы говорите, что base:: abc может только throw exp1. Однако, если у вас есть указатель базы типов, который действительно указывает на экземпляр sub, внезапно abc может выдать exp2 в дополнение к exp1.
Чтобы устранить проблему, вам нужно удалить exp2 из спецификатора throw в подклассе или добавить exp2 в спецификатор throw суперкласса.
Ответ 3
Предположим, что я пытаюсь
base *b = new sub;
b->abc();
Основываясь на спецификаторе throw в base::abc
, я ожидаю, что он будет только бросать exp1
; но sub::abc
говорит, что он также может бросать exp2
.
Если sub::abc
действительно может выбросить exp2
, добавьте exp2
в список того, что может base::abc
. Если нет, удалите его из списка sub::abc
.
И лучше: не используйте спецификаторы throw. Для получения дополнительной информации см. Может ли кто-нибудь объяснить спецификации исключения С++ для меня? и http://www.gotw.ca/publications/mill22.htm.