C++ Exception Handling: defining exception as object - c++

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?

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();
}

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.)

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.

Related

Exception not be caught by class and visual studio 2019 stopping at "Exception Unhandled"

I'm trying to create a class with a method to handle all exceptions. It accepts a pointer to a function, executes that function and then will handle if the function throws an exception. I then created a function get an invalid substring to prove the exception is caught, however, my class isn't getting the exception and Visual Studio is breaking on the substring line saying "Exception Unhandled"
cpp file:
#include "TestHarness.h"
using namespace TestHarness;
int testFunc();
int main()
{
Tester myTest;
std::cout << myTest.execute(testFunc);
return 0;
}
int testFunc()
{
std::cout << "My Test Func" << std::endl << std::endl;
std::string("abc").substr(10);
return 6;
}
h file:
#define TESTHARNESS_H
#include <vector>
#include <iostream>
#include <sstream>
#include <string>
namespace TestHarness
{
class Tester
{
public:
int execute(int(*func)());
private:
bool result;
};
int Tester::execute(int(*func)())
{
try {
(*func)();
result = true;
return 1;
}
catch (const std::runtime_error& e)
{
std::cout << e.what();
result = false;
return 0;
}
}
}
#endif
It's simple, really: substr throws std::out_of_range, which does not derive from std::runtime_error but from std::logic_error, itself derived from std::exception. Just catch std::exception const & or std::logic_error const &. Here is a list of inheritance for all standard exception types.

C++ Exceptions and handling

I am new to writing exceptions in c++ and I am struggling with an error. I won't get very much into detail 'cause I don't think this is relevant for the problem that I have.
#ifndef _STUDENT_H_
#define _STUDENT_H_
#include <string>
#include <map>
#include <vector>
#include <stdexcept>
#include <iostream>
class NoMarkException: public exception
{
public: NoMarkException():exception(){
cout<< "No marks were found." << endl;
}/*
NoMarkException(const string &name){
cout << "No marks for " << name << " were found."<< endl;
}*/
};
#endif
This is my NoMarkException class
float Student::getMaxMark() const throw(NoMarkException) {
if (marks.empty()) {
throw NoMarkException::NoMarkException();
}
float final = 0;
for (it = marks.begin(); it != marks.end(); it++) {
if ((*it).second > final) {
final = (*it).second;
}
}
return final;
}
And this is my Student.cpp
When I am building the project I get error: cannot call constructor 'NoMarkException::NoMarkException' directly
Any ideas why it is causing the problem?
if (marks.empty()) {
throw NoMarkException();
}
The error you get does not actually have anything to do with the fact you're using an exception class. The problem is that you're trying to instantiate an object of class NoMarkException by explicitly calling the (default) constructor, NoMarkException::NoMarkException(). In C++ you don't call constructors explicitly; rather, when you define a new variable, an appropriate constructor gets called. For example
void foo() {
std::vector<int> v(5);
NoMarkException my_exception();
NoMarkException my_other_exception();
}
or, using equivalent but more appropriate due to recent language changes:
void foo() {
std::vector<int> v { 5 };
NoMarkException my_exception { };
NoMarkException my_other_exception { };
}
In this case (both syntax alternatives), the constructors:
std::vector<int>::vector(std::vector<int>::size_type count)
NoMarkException::NoMarkException()
NoMarkException::NoMarkException()
are called (*).
In your case, you simply need to replace the explicit call you make to NoMarkException::NoMarkException() in the throw with an instantiation of NoMarkException object, i.e. your statement will be:
throw NoMarkException();
(*) - actually, the vector constructor that's called has a few more parameters which take their default values. See here.

Input Stream Operator lookup order with Boost.Program_options

I have an enumeration class and a corresponding input stream operator in the namespace fw::example.
#include <stdexcept>
#include <string>
#include <istream>
namespace fw {
namespace example {
enum class Booleans {
kFalse = 0,
kTrue = 1
};
std::istream& operator>>(std::istream& is, Booleans& boolean) {
std::string token;
is >> token;
if ("true" == token) {
boolean = Booleans::kTrue;
} else if ("false" == token) {
boolean = Booleans::kFalse;
} else {
throw std::invalid_argument{
"Invalid string representation for an enumerator of the Booleans class."};
}
return is;
}
} // namespace example
} // namespace fw
Then I bind a variable of that enum via Boost.Program_options in the same namespace:
// [...]
description_.add_options()(
"bool",
boost::program_options::value<Booleans>(&boolean_)
->required()
->default_value(Booleans::kFalse),
"A boolean string, either true or false.");
// [...]
But I do not want to expose the std::runtime_error to the user, instead I want
to use the proper exception from the framework, and that is boost::program_options::invalid_option_value.
Imagine a more complex scenario in which the enum class and the input stream operator are defined in a library and I am unable to modify that library.
So I tried the following (according to an answer I found on SO, which I can not find again):
namespace boost {
namespace program_options {
std::istream& operator>>(std::istream& is,
fw::example::Booleans& boolean) {
try {
return fw::example::operator>>(is, boolean);
} catch (std::invalid_argument const& kException) {
throw invalid_option_value{kException.what()};
}
}
} // namespace program_options
} // namespace boost
The whole code compiles, but the thing is, that only the free function fw::example::operator>> is called and therefore the wrong execption is propagated:
terminate called after throwing an instance of 'std::invalid_argument'
what(): Invalid string representation for an enumerator of the Booleans class.
I am looking for a solution to be able to cleanly separate the Boost.Program_options related code from the rest, but also use the appropriate exception.
I am using the following environment:
Boost v1.49
GCC v4.71 with the -std=c++11 argument.
The problem appears to be that you're (ab)using the streaming operator to do validation.
Instead, supply a Custom Validator to do the validation.
In that case you no longer have the conflict with the behaviour of operator<<.
The best you could hope for when adding a competing overload inside the program_options namespace would be that the compiler would find the overload acceptable /too/ and hence fail to compile it with "ambiguous overload"
Thanks to the user #sehe, I came up with the solution presented in this answer using standard stream operators and a Custom Validator of Boost.Program_options.
Ignoring the DRY issue (as in the source comments mentioned), the solution looks pretty clean. I also incorporated the common pitfall desribed in https://stackoverflow.com/a/5517755/891439.
Source Code using GCC v4.81 and Boost.Program_options v1.56:
#include <cstdint>
#include <iostream>
#include <stdexcept>
#include <sstream>
#include <string>
#include "boost/any.hpp"
#include "boost/program_options.hpp"
// Imagine the source code in the following namespace block is placed in an
// external library.
// The mapping between enumerators and strings violates the DRY principle, but
// that issue can be easily fixed, e. g. by using one [Boost.Bimap][4].
namespace fw {
namespace example {
enum class Booleans : std::uint8_t {
kFalse = 0,
kTrue = 1
};
std::ostream& operator<<(std::ostream& os, Booleans const& kBoolean) {
switch (kBoolean) {
case Booleans::kFalse:
os << "false";
break;
case Booleans::kTrue:
os << "true";
break;
default:
os.setstate(std::ios_base::failbit);
break;
}
return os;
}
std::istream& operator>>(std::istream& is, Booleans& boolean) {
std::string token;
is >> token;
if ("true" == token) {
boolean = Booleans::kTrue;
} else if ("false" == token) {
boolean = Booleans::kFalse;
} else {
is.setstate(std::ios_base::failbit);
}
return is;
}
} // namespace example
} // namespace fw
// The following source code is application specific code.
namespace fw {
namespace example {
void validate(boost::any& value,
std::vector<std::string> const& kValues,
fw::example::Booleans*,
int) {
boost::program_options::validators::check_first_occurrence(value);
std::string const& kStringValue{
boost::program_options::validators::get_single_string(kValues)};
std::istringstream iss{kStringValue};
Booleans real_value;
iss >> real_value;
if (!iss) {
throw boost::program_options::validation_error{
boost::program_options::validation_error::invalid_option_value};
}
value = boost::any{real_value};
}
} // namespace example
} // namespace fw
int main(int argc, char** argv) {
fw::example::Booleans boolean;
boost::program_options::variables_map variables_map;
boost::program_options::options_description options_description{
"Allowed Options"};
options_description.add_options()
("help,h", "Display the help message.")
("bool",
boost::program_options::value<fw::example::Booleans>(
&boolean)->required(),
"Set the boolean value.");
try {
boost::program_options::store(
boost::program_options::parse_command_line(argc,
argv,
options_description),
variables_map);
if (variables_map.count("help")) {
std::cout << options_description << "\n";
return 1;
}
boost::program_options::notify(variables_map);
} catch (boost::program_options::error const &kException) {
std::cerr << "Program Options Error: "
<< kException.what()
<< "\n\nSpecify -help for further information.\n";
return 2;
}
if (variables_map.count("bool")) {
std::cout << "The boolean value was set to "
<< variables_map["bool"].as<fw::example::Booleans>()
<< ".\n";
}
}
Can anyone provide further improvement suggestions?
Any general comments regarding the source code?

A pointer to a bound function may only be used to call the function

I'm working on a homework assignment for my C++ class and have ran across a problem that I cannot figure out what I am doing wrong.
Just to note, the separation of the files is necessary and I realize this would be much easier if I just made a structure AttackStyles inside the main and forgo the additional class file altogether.
The base of my problem is that I cannot seem to be able to loop through an array of classes and pull out base data. Here is the code:
// AttackStyles.h
#ifndef ATTACKSTYLES_H
#define ATTACKSTYLES_H
#include <iostream>
#include <string>
using namespace std;
class AttackStyles
{
private:
int styleId;
string styleName;
public:
// Constructors
AttackStyles(); // default
AttackStyles(int, string);
// Destructor
~AttackStyles();
// Mutators
void setStyleId(int);
void setStyleName(string);
// Accessors
int getStyleId();
string getStyleName();
// Functions
};
#endif
/////////////////////////////////////////////////////////
// AttackStyles.cpp
#include <iostream>
#include <string>
#include "AttackStyles.h"
using namespace std;
// Default Constructor
AttackStyles::AttackStyles()
{}
// Overloaded Constructor
AttackStyles::AttackStyles(int i, string n)
{
setStyleId(i);
setStyleName(n);
}
// Destructor
AttackStyles::~AttackStyles()
{}
// Mutator
void AttackStyles::setStyleId(int i)
{
styleId = i;
}
void AttackStyles::setStyleName(string n)
{
styleName = n;
}
// Accessors
int AttackStyles::getStyleId()
{
return styleId;
}
string AttackStyles::getStyleName()
{
return styleName;
}
//////////////////////////////////////////////
// main.cpp
#include <cstdlib>
#include <iostream>
#include <string>
#include "attackStyles.h"
using namespace std;
int main()
{
const int STYLE_COUNT = 3;
AttackStyles asa[STYLE_COUNT] = {AttackStyles(1, "First"),
AttackStyles(2, "Second"),
AttackStyles(3, "Third")};
// Pointer for the array
AttackStyles *ptrAsa = asa;
for (int i = 0; i <= 2; i++)
{
cout << "Style Id:\t" << ptrAsa->getStyleId << endl;
cout << "Style Name:\t" << ptrAsa->getStyleName << endl;
ptrAsa++;
}
system("PAUSE");
return EXIT_SUCCESS;
}
My question is why do I get the error:
"a pointer to a bound function may only be used to call the function"
on both ptrAsa->getStyleId and ptrAsa->getStyleName?
I cannot figure out what is wrong with this!
You are missing () around the function calls. It should be ptrAsa->getStyleId().
You are missing parenthesis on both calls, it should be
ptrAsa->getStyleId()
to call the function.
ptrAsa->getStyleId
is used to refer to a member value / attribute.
You need to invoke the function, not merely reference it:
std::cout << "Style Id:\t" << ptrAsa->getStyleId() << "\n";
std::cout << "Style Name:\t" << ptrAsa->getStyleName() << "\n";
You are Forgot to put () in last in Your Function(ptrAsa->getStyleId ) Calling with arrow operator.

try-catch with exceptions defined in template class

I'm trying to implement a priority queue using a linked list, but I'm having issues with try/catch. Here are the relevant parts of the priority queue header file:
#ifndef PRIORITYQUEUELINKED_H
#define PRIORITYQUEUELINKED_H
#include "RuntimeException.h"
#include <list>
using namespace std;
template <typename E, typename C> // uses data type and some total order relation
class PriorityQueueLinked {
// code for PriorityQueueLinked
class EmptyPriorityQueueException : public RuntimeException {
public:
EmptyPriorityQueueException() :
RuntimeException("Empty priority queue") {}
};
// more code
#endif
Here is the RuntimeException header file:
#ifndef RUNTIMEEXCEPTION_H_
#define RUNTIMEEXCEPTION_H_
#include <string>
class RuntimeException {// generic run-time exception
private:
std::string errorMsg;
public:
RuntimeException(const std::string& err) { errorMsg = err; }
std::string getMessage() const { return errorMsg; }
};
inline std::ostream& operator<<(std::ostream& out, const RuntimeException& e)
{
out << e.getMessage();
return out;
}
#endif
Here is my main:
#include "PriorityQueueLinked.h"
#include "Comparator.h"
#include <iostream>
using namespace std;
int main() {
try {
PriorityQueueLinked<int,isLess> prique; // empty priority queue
prique.removeMin(); // throw EmptyPriorityQueueException
}
catch(...) {
cout << "error" << endl << endl;
}
getchar();
return 0;
}
My problem lies in not being able to configure a replacement for the "..." for catch. I've tried several things, one of them: "catch(PriorityQueueLinked < int,isLess > ::EmptyPriorityQueueException E)", but in this case it says that EmptyPriorityQueueException is not a member of PriorityQueueLinked. Any advice would be greatly appreciated.
Thanks
Try-catch supports inheritance with exception classes. catch (const RuntimeException & ex) will catch any subclass of RuntimeException, even if its private. This is the whole point of deriving exception classes.
By the way, never write using namespace std; is a header, you can never know who include it, and how. Also the standard library already has your genereal purpose exception class, and what a surprise! They also clall it runtime exception, exception it§s written like this: std::runtime_exception. You can find it in <stdexcept>.