Reputation: 3
I am incredibly new to C++ and I have an assignment to create a test program for exception handling. I am having problems catching the exceptions, both those defined in the given classes and those I have defined in main. Could someone look over what I have and point out where I'm going wrong?
From the professor:
#ifndef STUDENT_H
#define STUDENT_H
#include <string>
using namespace std;
class Student
{
public:
Student();
Student(string thisStudentID);
void enroll(string thisSectionID);
private:
string studentID;
bool timeToThrow();
static int sneakyCount;
};
#endif
#include <string>
#include <iostream>
#include "Student.h"
#include "StudentException.h"
using namespace std;
// The constructor for this class accepts a Student ID
Student::Student(string thisStudentID)
{
// This first statement updates a variable used to help decide when to Throw an Exception
sneakyCount++;
// Any text will be accepted as the student ID in this implementation
if (!timeToThrow())
studentID = thisStudentID;
else
throw StudentException("Student " + thisStudentID + " has been expelled from this school");
}
// This default constructor shouldn't be used, so throwing an exception isn't so artificial, its
// the right thing to do. We will also find out if this constructor gets called at time that we don't expect.
Student::Student()
{
// This first statement updates a variable used to help decide when to Throw an Exception
sneakyCount++;
throw StudentException("Incorrect Call to Student Constructor - No Student ID Provided");
}
// This dummy function would enroll the student in a course
void Student::enroll(string thisSectionID)
{
// This first statement updates a variable used to help decide when to Throw an Exception
sneakyCount++;
if (!timeToThrow())
cout << endl << "Student: " << studentID << " is now enrolled in " << thisSectionID << endl;
else
throw StudentException("Section " + thisSectionID + " has been cancelled");
return;
}
// This is the code that helps decide when to throw an exception. You are welcome to look at it,
// but its only here to help generate unexpected exceptions. It will vary in different versions of Student
// as I play around with it.
int Student::sneakyCount = 0;
bool Student::timeToThrow()
{
if (sneakyCount == 4)
return true;
else
return false;
}
#ifndef STUDENTEXCEPTION_H
#define STUDENTEXCEPTION_H
#include <string>
using namespace std;
class StudentException
{
public:
StudentException(string thisErrorMessage);
string errorMessage();
private:
string message;
};
#endif
#include <string>
#include "StudentException.h"
using namespace std;
StudentException::StudentException(string whatWentWrong)
{
// Set the stored message within the object
// Any text will be accepted as the error message
message = whatWentWrong;
}
// Return the error message stored inside the object
string StudentException::errorMessage()
{
return message;
}
My code for the test program:
#include <iostream>
#include <string>
#include "StudentException.h"
#include "Student.h"
using namespace std;
int main()
{
char again = 'n';
do
{
try
{
Student testStudent1("S0000001");
testStudent1.enroll("CSC-160-500");
}
catch(StudentException())
{
StudentException testException1("Pre-requisites required");
cout << testException1.errorMessage();
}
cout << "Again?\n";
cin >> again;
}
while(tolower(again) == 'y');
return 0;
}
I only have the loop for easier testing as the Exception throwing is somewhat random. I only catch exceptions if I use catch(...). Any hints on what I'm doing wrong?
Upvotes: 0
Views: 220
Reputation: 36463
catch(StudentException())
{
StudentException testException1("Pre-requisites required");
cout << testException1.errorMessage();
}
That's not the way to do it. Your catch
doesn't catch the actual exception, you should make it an argument :
catch(const StudentException& ex)
{
cout << ex.errorMessage();
}
Upvotes: 1
Reputation: 16824
catch(StudentException()) {
...
}
This is the wrong syntax. You need to say
catch(const StudentException& e) {
...
}
While we're here, it's usually a good idea for exceptions to inherit from one of the standard library's exception classes, for example
class StudentException : public std::runtime_error
{
public:
StudentException(const string& thisErrorMessage)
: std::runtime_error(thisErrorMessage)
{}
};
Not only does is this easier to implement, but it also provides the what()
member function, which people will usually look for to find the exception message.
Upvotes: 1
Reputation: 72271
catch(StudentException())
tries to catch a function type. You want
catch (StudentException& se)
(and then you can use se
in the handler instead of constructing a new unrelated StudentException
.)
Upvotes: 1