Ошибка спецификатора броска в C ++ - PullRequest
10 голосов
/ 11 марта 2011

Следующий код генерирует «Ошибка спецификатора броска 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)
{
    .....
}

Ответы [ 3 ]

13 голосов
/ 11 марта 2011

Проблема возникает из-за того, что подкласс должен использоваться везде, где может использоваться базовый класс, и поэтому не должен выбрасывать какие-либо типы исключений, кроме тех, которые указаны в базовом классе.

Существует три решения:

  1. Измените спецификатор базового класса, включив в него каждый тип исключения, который может понадобиться любому подклассу
  2. Измените каждый подкласс для обработки каждого типа исключения, кроме указанных в базовом классе
  3. Удалить спецификаторы исключений.

Я бы предложил их удалить;они широко расценены как плохая идея, частично из-за проблем как это.Как указывает Матье, Комитет по стандартизации соглашается, и спецификаторы исключений должны быть исключены в следующей версии Стандарта.

6 голосов
/ 11 марта 2011

Когда вы переопределяете виртуальный метод с помощью спецификатора throw в производном классе, метод в производном классе не может выбросить больше исключений, чем метод в суперклассе.Если вам было разрешено это сделать, вы могли бы разорвать контракт, созданный публичным API суперкласса, переопределив методы в подклассе.

В вашем примере вы говорите, что base :: abc может генерировать только exp1.Однако, если у вас есть указатель типа base, который действительно указывает на экземпляр sub, неожиданно abc может выдать exp2 в дополнение к exp1.

Чтобы устранить проблему, необходимо удалить exp2 изспецификатор throw в подклассе или добавление exp2 к спецификатору throw суперкласса.

3 голосов
/ 11 марта 2011

Предположим, я пытаюсь

base *b = new sub;
b->abc();

Исходя из спецификатора броска в base::abc, я ожидаю, что он только бросает exp1; но sub::abc говорит, что может также выбросить exp2.

Если sub::abc действительно может бросить exp2, то добавьте exp2 в список того, что base::abc может бросить. Если нет, то удалите его из списка sub::abc.

И лучше: не используйте спецификаторы броска. Для получения дополнительной информации см. Может кто-нибудь объяснить мне спецификации исключений C ++? и http://www.gotw.ca/publications/mill22.htm.

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