Marina
Marina

Reputation: 49

can't create two custom exception classes inheriting from std::logic_error

My assignment for my cs class is to create two custom exception classes inheriting from std::logic_error: OverflowingSwimmingPoolException and UnderflowingSwimmingPoolException. When an illegal operation is attempted, create and throw a custom exception, rather than just printing an error message. Include try...catch blocks in your driver code to catch any exceptions.

this is the part of my header file:

    #ifndef SWIMMINGPOOL_H
    #define SWIMMINGPOOL_H
    #include <stdexcept>
    #include <iostream>
    using namespace std;



 namespace cs52
  {
          class OverflowingSwimmingPoolException: public logic_error
  {

    OverflowingSwimmingPoolException (){};

};

class UnderflowingSwimmingPoolException: public logic_error
{

    UnderflowingSwimmingPoolException(){};
};

here is the compiler says on the line where constructor is: Constructor for 'cs52::UnderflowingSwimmingPoolException' must explicitly initialize the base class 'std::logic_error' which does not have a default constructor.

That is what I have in my implementation file:

    #include "SwimmingPool.h"
    #include <stdexcept>
    #include <iostream>
     using namespace std;



     namespace cs52
     {       
      SwimmingPool operator +(const SwimmingPool& pool1, const SwimmingPool&         pool2) throw (OverflowingSwimmingPoolException, UnderflowingSwimmingPoolException)
{
    SwimmingPool temp;
    temp.mySize = pool1.mySize+pool2.mySize;
    temp.myContents = pool1.myContents+pool2.myContents;
    if (temp.myContents>temp.mySize)
   throw OverflowingSwimmingPoolException();
    return temp;
}
SwimmingPool operator -(const SwimmingPool& pool1, const SwimmingPool& pool2) throw (OverflowingSwimmingPoolException, UnderflowingSwimmingPoolException)
{
    SwimmingPool temp;
    temp.mySize= pool1.mySize-pool2.mySize;
    temp.myContents= pool1.myContents-pool2.myContents;
    if (temp.myContents>temp.mySize)
        throw OverflowingSwimmingPoolException();
    if (temp.myContents<0 || temp.mySize<0)
        throw UnderflowingSwimmingPoolException();
    return temp;
}
}

the compiler shows the error in the line where I throw the exception class. it says: calling a private constructor of class cs53:OverflowingSwimmimgPoolException.

and the part of my driver file should look something like that:

   using namespace cs52;
   try {
    SwimmingPool badPool = smallOne - bigOne;
    cout << "This should never happen..." << endl;
    } 
    catch( UnderflowingSwimmingPoolException uspe ) {
    cout << "working..." << endl;
    } 
    catch( OverflowingSwimmingPoolException uspe ) {
    cout << "This should never happen..." << endl;
    }

I have just started to code, so I do not really understand how the classes like std::logic_error that are already created in the libraries work.

Upvotes: 1

Views: 800

Answers (3)

mr.stobbe
mr.stobbe

Reputation: 612

The compiler message, "must explicitly initialize the base class 'std::logic_error' which does not have a default constructor" is because std::logic_error requires an argument during initialization. Specifically, it requires a string. For example:

class my_exception: public std::logic_error {
    my_exception() { };
}

... will not work, but...

class my_exception: public std::logic_error {
    my_exception(const char* what): std::logic_error(what) { };
}

... will because there is no constructor std::logic_error::logic_error() but there is one std::logic_error::logic_error(const char*).

If you would like to specify an exception "reason" (as given by what) statically for a specific exception class, you can specify it during construction such as...

class my_exception: public std::logic_error {
    my_exception(): std::logic_error("Oh No!") { };
}

All standard exceptions inherit from std::exception which expects a reason for the exception. Later, this reason can be used similar to...

try {
    throw my_exception();
} catch (const std::exception& e) { // << because you inherited this class
    std::cerr << "error: " << e.what() << std::endl;
}

... which would print "error: Oh No!" using the previous example.

Specifically, see std::logic_error an std::exception for more details.

Upvotes: 0

BoBTFish
BoBTFish

Reputation: 19777

In your constructor for the derived exception, you must call the constructor of the base class, which takes a string containing some error text, like this:

OverflowingSwimmingPoolException ()
  : std::logic_error("It's all gone horribly wrong!")
{};

This will then be returned when you call what() on the caught exception (assuming you don't override it with different behaviour; but don't do that):

try {
    // ...
} catch (std::exception const& e) {
    std::cerr << e.what() << '\n'; // Prints "It's all gone horribly wrong!"
}

It is common for the interface of an exception type to take a string for this purpose, but of course for your own exception types, you don't have to.

Note that if you catch the exception using the base class, make sure you catch by reference (or reference-to-const), to avoid object slicing.

Upvotes: 1

Some programmer dude
Some programmer dude

Reputation: 409472

The error is quite clear and have nothing to do with the logic or when, where and how you throw the exceptions. It's only about the exception classes themselves and the constructor.

Note how the error says that you must initialize the parent class? You can do that with a constructor initializer list, like e.g.

OverflowingSwimmingPoolException ()
    : std::logic_error("Some error message")
{}

The error message in the std::logic_error initialization is what the what function will report.

Upvotes: 1

Related Questions