#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 для выполнения этого во время выполнения?