ChrisMcJava
ChrisMcJava

Reputation: 2303

differences in constructor syntax when creating exceptions (c++)

So background, I have a strong background in the Java programming language. I am a total noob when it comes to the C++ language. Basically I know that there are two different syntaxes for defining constructors in C++, I just do not understand the difference.

When writing the an exception constructor as follows (in a manor similar to a method without a return type), the compiler outputs a no matching function for call to 'std::runtime_error::runtime_error()' error:

#include <stdexcept>
using namespace std;

class DivideByZeroException : public runtime_error {
public :
    DivideByZeroException() {
        runtime_error("attempted to divide by zero.");
    }
};

But, when the constructor is modified to the following, the code compiles error-free:

#include <stdexcept>
using namespace std;

class DivideByZeroException : public runtime_error {
public :
    DivideByZeroException() :
        runtime_error("attempted to divide by zero."){};
};

Could someone please explain what is going on here?

Upvotes: 0

Views: 139

Answers (2)

Benjamin Lindley
Benjamin Lindley

Reputation: 103751

In the second example, the part between the colon and the opening brace is called the initialization list. It's where you initialize members and base classes. If you don't use the initialization list (as in your first example), your members and base classes are default initialized. But std::runtime_error has no default constructor, that's the reason for your error.

no matching function for call to 'std::runtime_error::runtime_error()'

The compiler is trying to call the default constructor for std::runtime_error, but it does not exist. So it must be initialized in the initialization list. As for the line of code in the constructor of your first example:

DivideByZeroException() {
    runtime_error("attempted to divide by zero.");   // this one
}

that constructs a temporary runtime_error object which is completely unrelated to the base member of the DivideByZeroException object. This temporary is destroyed at the end of the expression.

Basically I know that there are two different syntaxes for defining constructors in C++

By this, I assume the two ways you mean are (1) with, and (2) without, the initialization list. This is true, usually. However, in some cases, as in yours, there is only one way. That is, with an initialization list.

Upvotes: 3

Sebastian Redl
Sebastian Redl

Reputation: 72215

There is nothing special about exceptions. (In fact, unlike Java, C++ doesn't see any difference whatsoever between an exception class and any other class, and you can throw ints, if you want.)

There's just one right syntax for constructors, and it's the second one. The first snippet does something different: first, it tries to call the base constructor without arguments (i.e. it's the same as if you had written DivideByZeroException() : runtime_error() { runtime_error("message"); }), and then it creates a temporary runtime_error object in the constructor body and immediately discards it (the runtime_error line in the body has roughly the same effect as writing new RuntimeException() by itself in Java).

The error happens because runtime_error doesn't have a constructor with no arguments, so the implicit attempt to call such a constructor fails.

Upvotes: 2

Related Questions