Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c++ with and without throw() in method/constructor signature for a custom exception

I am beginner in c++, and hence apologies for this silly question. I am posting it here because I cannot find a similar answer on stackoverflow.

I was progressing through exceptions in C++ and as I was doing some hands on with custom exceptions, I have this code

class MyException: public std::exception{
public:
    virtual const char* what() const throw() {
        return "something bad happened";
    }

};

// class that throws above exception

class canGoWrong {
public:
    canGoWrong(){
        throw MyException();
    }
};

The above code was shown by the teacher. The constructor just implemented a virtual function defined in the base class exception. I got till there.

Now when I was trying a different version to practice, I tried to use a custom function instead of re-defining the virtual (as c++ doesn't strictly enforce the concept of interface, please correct me if I am wrong here.)

I wrote it as

class my_custom_shit_exception: public std::exception {
public:
    const char* show() { // I omitted the const throw() here
            return "This is an error encountered\n";
    }
};

class myclass {
public:
    myclass() {
        throw my_custom_shit_exception();
    }
};

To summarise, I didn't find a difference in behaviour in both ways

public:
const char* show() {
        return "This is an error encountered\n";
}
virtual const char* what() const throw() {
    return "something bad happened";
}
  • So why was the const throw() used in the what() virtual function? What difference it makes?

Thanks to all.

like image 652
file2cable Avatar asked Sep 02 '17 07:09

file2cable


People also ask

Which function must be overridden when creating a custom exception class?

Custom exceptions provide relevant information about an error to the exception handling mechanism. They can be generated by creating a new class containing the attributes needed and throwing an instance of such a class, or by inheriting from std::exception and overriding the what() function.

What happens when exception is thrown?

When an exception is thrown using the throw keyword, the flow of execution of the program is stopped and the control is transferred to the nearest enclosing try-catch block that matches the type of exception thrown. If no such match is found, the default exception handler terminates the program.

When should a function throw an exception?

5.1 Understanding Exception HandlingIf the detecting function cannot deal with the anomaly, it "throws" an exception. A function that "handles" that kind of exception catches it. In C++, when an exception is thrown, it cannot be ignored--there must be some kind of notification or termination of the program.

Can we define our own exception in CPP?

A C++ exception is a response to an exceptional circumstance that arises while a program is running, such as an attempt to divide by zero. Exceptions provide a way to transfer control from one part of a program to another. C++ exception handling is built upon three keywords: try, catch, and throw.


2 Answers

The function signature

class std::exception {
    //...
public:
    virtual const char* what() const throw();
    //...
};

can be read as: what is a virtual member function of std::exception which returns a pointer to a constant character (array) and which does not modify members of that object (hence the 2nd const) and which guarantees not to throw an exception in its code.

Beware that the exception-specification is nowadays deprecated: Instead, since C++11 there is the noexcept specifier to declare functions that "guarantee" not to throw exceptions. Additionally, since C++17 the throw() has become a synonym for noexcept(true), but with a slightly different behaviour.

For more details, refer to this description of noexcept.

There it also says: "Note that a noexcept specification on a function is not a compile-time check; it is merely a method for a programmer to inform the compiler whether or not a function should throw exceptions. The compiler can use this information to enable certain optimizations on non-throwing functions [...]".

like image 166
King Thrushbeard Avatar answered Nov 02 '22 23:11

King Thrushbeard


I wanted to show some quotes from Scott Meyers

"Effective C++" Third Edition

int doSomething() throw(); // note empty exception spec.

This doesn’t say that doSomething will never throw an exception; it says that if doSomething throws an exception, it’s a serious error, and the unexpected function should be called. †

For information on the unexpected function, consult your favorite search engine or comprehensive C++ text. (You’ll probably have better luck searching for set_unexpected, the function that specifies the unexpected function.)

And from the "Effective Modern C++"

In C++11, unconditional noexcept is for functions that guarantee they won’t emit exceptions.

If, at runtime, an exception leaves f, f’s exception specification is violated. With the C++98 exception specification, the call stack is unwound to f’s caller, and, after some actions not relevant here, program execution is terminated. With the C++11 exception specification, runtime behavior is slightly different: the stack is only possibly unwound before program execution is terminated. The difference between unwinding the call stack and possibly unwinding it has a surprisingly large impact on code generation. In a noexcept function, optimizers need not keep the runtime stack in an unwindable state if an exception would propagate out of the function, nor must they ensure that objects in a noexcept function are destroyed in the inverse order of construction should an exception leave the function. Functions with “throw()” exception specifications lack such optimization flexibility, as do functions with no exception specification at all.

like image 30
Artemy Vysotsky Avatar answered Nov 03 '22 01:11

Artemy Vysotsky