Перехват класса исключений в шаблоне

#c #templates #exception #exception-handling #overflow

#c #шаблоны #исключение #переполнение

Вопрос:

У меня возникла проблема с использованием переполнения класса исключений () для шаблона стека, который я создаю. Если я определяю класс регулярно, проблем не возникает. Если я определяю класс как шаблон, я не могу заставить свой вызов catch() работать должным образом. У меня такое чувство, что это просто синтаксис, но я ни за что на свете не могу в этом разобраться.

 #include<iostream>
#include<exception>
using namespace std;

template <class T>
class Stack
{
private:
    T *stackArray;
    int size;
    int top;

public: 
    Stack(int size) { this->size = size; stackArray = new T[size]; top = 0; }
    ~Stack() { delete[] stackArray; }

    void push(T value)
    {
        if (isFull())
            throw Overflow();
        stackArray[top] = value;
        top  ;
    }

    bool isFull()
    {
        if (top == size)
            return true;
        else
            return false;
    }

    class Overflow {};

};

int main()
{
    try
    {
        Stack<double> Stack(5);
        Stack.push( 5.0);
        Stack.push(10.1);
        Stack.push(15.2);
        Stack.push(20.3);
        Stack.push(25.4);
        Stack.push(30.5);
    }
    catch (Stack::Overflow)
    {
        cout << "ERROR! The stack is full.n";
    }

    return 0;
}
  

Проблема заключается в инструкции catch (Stack::Overflow). Как я уже сказал, если класс не является шаблоном, это работает просто отлично. Однако, как только я определяю его как шаблон, это перестает работать. Я перепробовал все виды синтаксиса, но я всегда получаю один из двух наборов сообщений об ошибках от компилятора.

Если я использую catch (Stack::Overflow):

 ch18pr01.cpp(89) : error C2955: 'Stack' : use of class template requires template argument list
ch18pr01.cpp(13) : see declaration of 'Stack'
ch18pr01.cpp(89) : error C2955: 'Stack' : use of class template requires template argument list
ch18pr01.cpp(13) : see declaration of 'Stack'
ch18pr01.cpp(89) : error C2316: 'Stack<T>::Overflow' : cannot be caught as the destructor and/or copy constructor are inaccessible
  

РЕДАКТИРОВАТЬ: я имел в виду
Если я использую catch (Stack<double>::Overflow) или любую его разновидность:

 ch18pr01.cpp(89) : error C2061: syntax error : identifier 'Stack'
ch18pr01.cpp(89) : error C2310: catch handlers must specify one type
ch18pr01.cpp(95) : error C2317: 'try' block starting on line '75' has no catch handlers
  

Я просто не могу в этом разобраться. У кого-нибудь есть какие-нибудь идеи?

Комментарии:

1. В вашей правке: это именно то, что имел в виду dark_charlie: не используйте одно и то же имя для типов и переменных!

Ответ №1:

Суть в том, что вы должны поместить

 class overflow;
  

вне

 class Stack<>
  

поскольку это общее исключение, не указан тип.

Комментарии:

1. кроме того, он должен наследоваться от std::exception.

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

Ответ №2:

 catch (const Stack<double>::Overflow amp; obj)
                 //^^^^^^^^ note this!
  

То есть вы также должны указать тип.

Также обратите внимание, что я принимаю объект в качестве const ссылки, чтобы избежать копирования исходного Overflow объекта!

Кстати, почему вы создали Overflow вложенный тип? Какое обоснование у вас есть? Я не вижу никаких веских причин для этого. Было бы лучше, если бы вы определили его вне Stack шаблона класса.

Комментарии:

1. Ранее я пытался использовать Stack<double>::Overflow, и это не решило мою проблему — пока я не изменил имя своей переменной на что-то отличное от имени класса. Что касается того, почему я вложил переполнение? Это то, что мой учебник предложил в своем примере программы.

2. @Todd: Имя вашего класса — Stack , и имя вашего объекта тоже Stack . Зачем вы это сделали? Ваша клавиатура не позволяет вводить другое имя?

3. Не нужно быть снисходительным… main() был предоставлен вместе с моим учебником, и я должен был создать класс шаблона вокруг него. Я бы не стал делать это самостоятельно.

4. @Todd: Вы имеете в виду, что в вашем учебнике одинаковое имя как для типа, так и для переменной?

5. Да. И он сказал мне также вложить класс Overflow().

Ответ №3:

Вы должны указать, какой экземпляр шаблона вы используете:

 try
{
    Stack<double> Stack(5);
    Stack.push( 5.0);
    Stack.push(10.1);
    Stack.push(15.2);
    Stack.push(20.3);
    Stack.push(25.4);
    Stack.push(30.5);
}
catch (Stack<double>::Overflow)
{
    cout << "ERROR! The stack is full.n";
}
  

Если вы не укажете аргумент template, компилятор будет сбит с толку, потому что он не знает, какой класс использовать (например, Stack<int> или Stack<double> ?).

Примечание: Старайтесь избегать использования одинаковых имен для типов и переменных ( Stack и Stack в этом примере), это затрудняет читаемость и отслеживание ошибок.

Комментарии:

1. Ранее я использовал catch (Stack<double>::Overflow) безрезультатно, но когда я изменил имя переменной, это сработало как по волшебству.

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