I designed several custom exceptions which all inherit from the same abstract base class custom::exception
and from the corresponding standard exception thanks to multiple inheritance.
Thus there is a specific hierarchy in my custom exceptions and I can catch them generically or specifically.
Now I switched on all warnings without any problem with GCC but clang complains about the virtual destructor :
#include <iostream>
#include <stdexcept>
namespace custom {
struct exception;
struct buffer_overflow;
struct null_pointer;
struct out_of_range;
//...
}
struct custom::exception {
virtual ~exception() noexcept {}
virtual const char* what() const noexcept = 0;
};
struct custom::null_pointer : public custom::exception, public std::logic_error {
null_pointer(const std::string &str): std::logic_error(str) {}
const char* what() const noexcept override { return std::logic_error::what(); }
};
int main(){
try{
throw custom::null_pointer("[ERROR] NULL pointer exception !");
}
catch(const custom::exception &error){
std::cout << error.what() << std::endl;
}
}
Output with g++ (MinGW.org GCC-8.2.0-3) :
[ERROR] NULL pointer exception !
Output with clang++ version 6.0.0-1ubuntu2 :
test.cpp:13:13: warning: definition of implicit copy constructor for 'exception' is deprecated because it has a
user-declared destructor [-Wdeprecated]
virtual ~exception() noexcept {}
^
test.cpp:17:16: note: in implicit copy constructor for 'custom::exception' first required here
struct custom::null_pointer : public custom::exception, public std::logic_error {
^
test.cpp:24:15: note: in implicit move constructor for 'custom::null_pointer' first required here
throw custom::null_pointer("[ERROR] NULL pointer exception !");
^
1 warning generated.
[ERROR] NULL pointer exception !
I do not really understand because custom::exception
is abstract and does not contain any member variable so it does not need user-defined constructors. But if I define those, clang does not complain :
struct custom::exception {
exception() noexcept {}
exception(const exception&) noexcept {}
virtual ~exception() noexcept {}
virtual const char* what() const noexcept = 0;
};
My questions are :
- Which compiler is correct ?
- Why do I have to define empty default & copy constructors such as above ?
Thank you.
Related questions :