具有多重继承和抽象基础的自定义异常中的用户定义的空构造函数 class
User-defined empty constructors in custom exception with multiple inheritance and abstract base class
我设计了几个自定义异常,它们都继承自相同的抽象基础 class custom::exception
和相应的标准 exception 由于多重继承。
因此在我的自定义异常中有一个特定的层次结构,我可以一般地或特定地捕获它们。
现在我打开所有警告,GCC 没有任何问题,但 clang 抱怨虚拟析构函数:
#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;
}
}
使用 g++ 输出 (MinGW.org GCC-8.2.0-3) :
[ERROR] NULL pointer exception !
用 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 !
我不是很明白,因为custom::exception
是抽象的,不包含任何成员变量,所以不需要用户自定义构造函数。但是如果我定义那些,clang 不会抱怨:
struct custom::exception {
exception() noexcept {}
exception(const exception&) noexcept {}
virtual ~exception() noexcept {}
virtual const char* what() const noexcept = 0;
};
我的问题是:
- 哪个编译器是正确的?
- 为什么我必须像上面那样定义空的默认构造函数和复制构造函数?
谢谢。
相关问题:
- C++ Abstract Class: constructor yes or no?
- Define default constructor for abstract base class
您遇到了 Warning: definition of implicit copy constructor is deprecated 遇到的相同问题:
在 C++ 标准 D.2 Implicit declaration of copy functions [depr.impldec]
中,C++17 N4659 草案指出:
The implicit definition of a copy constructor as defaulted is
deprecated if the class has a user-declared copy assignment operator
or a user-declared destructor. The implicit definition of a copy
assignment operator as defaulted is deprecated if the class has a
user-declared copy constructor or a user-declared destructor (15.4,
15.8). In a future revision of this International Standard, these implicit definitions could become deleted (11.4).
这给出了
的答案
1.: 两个编译器都是正确的,clang 实际上会警告你弃用,gcc 不会,这也没关系。
这没问题,因为 D(0) 对其发出警告是可选的,甚至 [[deprecated]]
属性也不是强制发出警告的:
An implementation may declare library names and entities described in
this section with the deprecated attribute
2。逼你想想所谓的Rule of Three:
三个规则指出,由于您需要定义一个构造函数,因此您可能需要一个复杂的复制和/或移动构造函数。通过强制你显式定义它们,即使使用 default
,它起到了保险的作用,class 作者已经考虑了切片和其他问题。然而,由于隐式或默认的复制构造函数只是复制你的基础和元素,你应该没问题。
你可以default,这基本上和隐含定义的东西一样,但你想要一个虚拟析构函数,否则是一样的:
exception() noexcept = default;
exception(const exception&) noexcept = default;
virtual ~exception() noexcept = default;
我设计了几个自定义异常,它们都继承自相同的抽象基础 class custom::exception
和相应的标准 exception 由于多重继承。
因此在我的自定义异常中有一个特定的层次结构,我可以一般地或特定地捕获它们。
现在我打开所有警告,GCC 没有任何问题,但 clang 抱怨虚拟析构函数:
#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;
}
}
使用 g++ 输出 (MinGW.org GCC-8.2.0-3) :
[ERROR] NULL pointer exception !
用 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 !
我不是很明白,因为custom::exception
是抽象的,不包含任何成员变量,所以不需要用户自定义构造函数。但是如果我定义那些,clang 不会抱怨:
struct custom::exception {
exception() noexcept {}
exception(const exception&) noexcept {}
virtual ~exception() noexcept {}
virtual const char* what() const noexcept = 0;
};
我的问题是:
- 哪个编译器是正确的?
- 为什么我必须像上面那样定义空的默认构造函数和复制构造函数?
谢谢。
相关问题:
- C++ Abstract Class: constructor yes or no?
- Define default constructor for abstract base class
您遇到了 Warning: definition of implicit copy constructor is deprecated 遇到的相同问题:
在 C++ 标准 D.2 Implicit declaration of copy functions [depr.impldec]
中,C++17 N4659 草案指出:
The implicit definition of a copy constructor as defaulted is deprecated if the class has a user-declared copy assignment operator or a user-declared destructor. The implicit definition of a copy assignment operator as defaulted is deprecated if the class has a user-declared copy constructor or a user-declared destructor (15.4, 15.8). In a future revision of this International Standard, these implicit definitions could become deleted (11.4).
这给出了
的答案1.: 两个编译器都是正确的,clang 实际上会警告你弃用,gcc 不会,这也没关系。
这没问题,因为 D(0) 对其发出警告是可选的,甚至 [[deprecated]]
属性也不是强制发出警告的:
An implementation may declare library names and entities described in this section with the deprecated attribute
2。逼你想想所谓的Rule of Three:
三个规则指出,由于您需要定义一个构造函数,因此您可能需要一个复杂的复制和/或移动构造函数。通过强制你显式定义它们,即使使用 default
,它起到了保险的作用,class 作者已经考虑了切片和其他问题。然而,由于隐式或默认的复制构造函数只是复制你的基础和元素,你应该没问题。
你可以default,这基本上和隐含定义的东西一样,但你想要一个虚拟析构函数,否则是一样的:
exception() noexcept = default;
exception(const exception&) noexcept = default;
virtual ~exception() noexcept = default;