从 std::exception 继承的 Boost 示例代码不会 link
Boost example code inheriting from std::exception doesn't link
这篇来自boost: Error and Exception Handling的文章给出了如下程序代码:
#include <iostream>
struct my_exc1 : std::exception {
char const* what() const throw();
};
struct my_exc2 : std::exception {
char const* what() const throw();
};
struct your_exc3 : my_exc1, my_exc2 {};
int main() {
try {
throw your_exc3();
} catch(std::exception const& e) {}
catch(...) {
std::cout << "whoops!" << std::endl;
}
}
使用 g++ (GCC) 5.2.0 编译时,我得到以下结果
> g++ -std=c++11 custom_exception.cpp
/tmp/ccmbzPOk.o: In function `my_exc1::my_exc1()':
custom_exception.cpp:(.text._ZN7my_exc1C2Ev[_ZN7my_exc1C5Ev]+0x19): undefined reference to `vtable for my_exc1'
/tmp/ccmbzPOk.o: In function `my_exc1::~my_exc1()':
custom_exception.cpp:(.text._ZN7my_exc1D2Ev[_ZN7my_exc1D5Ev]+0xd): undefined reference to `vtable for my_exc1'
/tmp/ccmbzPOk.o: In function `my_exc2::my_exc2()':
custom_exception.cpp:(.text._ZN7my_exc2C2Ev[_ZN7my_exc2C5Ev]+0x19): undefined reference to `vtable for my_exc2'
/tmp/ccmbzPOk.o: In function `my_exc2::~my_exc2()':
custom_exception.cpp:(.text._ZN7my_exc2D2Ev[_ZN7my_exc2D5Ev]+0xd): undefined reference to `vtable for my_exc2'
/tmp/ccmbzPOk.o:(.rodata._ZTV9your_exc3[_ZTV9your_exc3]+0x20): undefined reference to `my_exc1::what() const'
/tmp/ccmbzPOk.o:(.rodata._ZTV9your_exc3[_ZTV9your_exc3]+0x48): undefined reference to `my_exc2::what() const'
/tmp/ccmbzPOk.o:(.rodata._ZTI9your_exc3[_ZTI9your_exc3]+0x18): undefined reference to `typeinfo for my_exc1'
/tmp/ccmbzPOk.o:(.rodata._ZTI9your_exc3[_ZTI9your_exc3]+0x28): undefined reference to `typeinfo for my_exc2'
collect2: error: ld returned 1 exit status
我在其他地方看到了相同的技术,这向我建议这应该编译(和 link)静默。 (例如,我引用 Anthony Williams C++ Concurrency in Action 第 45 页,他从 std::exception
继承了线程安全堆栈示例 empty_stack
。 )
我已经尝试 #include <exception>
尽管这不是 C++ 库问题,但我什至在有类似问题的人的建议下尝试了 -lstdc++
标志---out绝望。
我知道在 std::exception
中,what()
是虚拟的,这意味着我应该定义它---所以我不确定为什么它应该首先编译,但我对它显然对其他人有用感到沮丧。
我的问题有两个:(1) 问题是什么,为什么对其他人有效? (2,有条件地)C++ 的新手,我还应该问什么是实现 what()
的好方法(假设我必须)以最小的方式,因为我实际上不想传递一个字符串我的例外。我不需要从层次结构的更深层次继承,例如 std::runtime_error
.
根据 C++14 (N3936) [basic.def.odr]/3:
A virtual member function is odr-used if it is not pure.
所以 my_exc1::what()
和 my_exc2::what()
是 odr-used,即使它们从未被调用过。然后我们有 [basic.def.odr]/4:
Every program shall contain exactly one definition of every non-inline function or variable that is odr-used in that program; no diagnostic required.
所以整个程序都有未定义的行为,但不需要 compiler/linker 来诊断它。
这种宽松要求的基本原理是让 link 人的工作更轻松:如果 link 人碰巧能够 link 而无需调用此函数或其他任何内容,那么它就可以这样做; C++ 标准不要求 linker 进行某种整体程序分析以确定是否所有 odr-used 函数都有主体。
所以这段代码有问题,它应该有这两个函数的主体。它还应该有 #include <exception>
。对于编译和执行此代码的人;他们的 iostream
包括 exception
(这是允许的但不是必需的),他们的 link 人将未定义的行为表现为 link 正确。
要提供正文,很简单:
char const *what() const throw() { return ""; }
(假设您可以在线执行)。当然,您可以 return 一些其他固定字符串,例如 "my_exc1"
。请注意,如果您只想 return ""
那么您根本不需要重新声明 what()
。
这篇来自boost: Error and Exception Handling的文章给出了如下程序代码:
#include <iostream>
struct my_exc1 : std::exception {
char const* what() const throw();
};
struct my_exc2 : std::exception {
char const* what() const throw();
};
struct your_exc3 : my_exc1, my_exc2 {};
int main() {
try {
throw your_exc3();
} catch(std::exception const& e) {}
catch(...) {
std::cout << "whoops!" << std::endl;
}
}
使用 g++ (GCC) 5.2.0 编译时,我得到以下结果
> g++ -std=c++11 custom_exception.cpp
/tmp/ccmbzPOk.o: In function `my_exc1::my_exc1()':
custom_exception.cpp:(.text._ZN7my_exc1C2Ev[_ZN7my_exc1C5Ev]+0x19): undefined reference to `vtable for my_exc1'
/tmp/ccmbzPOk.o: In function `my_exc1::~my_exc1()':
custom_exception.cpp:(.text._ZN7my_exc1D2Ev[_ZN7my_exc1D5Ev]+0xd): undefined reference to `vtable for my_exc1'
/tmp/ccmbzPOk.o: In function `my_exc2::my_exc2()':
custom_exception.cpp:(.text._ZN7my_exc2C2Ev[_ZN7my_exc2C5Ev]+0x19): undefined reference to `vtable for my_exc2'
/tmp/ccmbzPOk.o: In function `my_exc2::~my_exc2()':
custom_exception.cpp:(.text._ZN7my_exc2D2Ev[_ZN7my_exc2D5Ev]+0xd): undefined reference to `vtable for my_exc2'
/tmp/ccmbzPOk.o:(.rodata._ZTV9your_exc3[_ZTV9your_exc3]+0x20): undefined reference to `my_exc1::what() const'
/tmp/ccmbzPOk.o:(.rodata._ZTV9your_exc3[_ZTV9your_exc3]+0x48): undefined reference to `my_exc2::what() const'
/tmp/ccmbzPOk.o:(.rodata._ZTI9your_exc3[_ZTI9your_exc3]+0x18): undefined reference to `typeinfo for my_exc1'
/tmp/ccmbzPOk.o:(.rodata._ZTI9your_exc3[_ZTI9your_exc3]+0x28): undefined reference to `typeinfo for my_exc2'
collect2: error: ld returned 1 exit status
我在其他地方看到了相同的技术,这向我建议这应该编译(和 link)静默。 (例如,我引用 Anthony Williams C++ Concurrency in Action 第 45 页,他从 std::exception
继承了线程安全堆栈示例 empty_stack
。 )
我已经尝试 #include <exception>
尽管这不是 C++ 库问题,但我什至在有类似问题的人的建议下尝试了 -lstdc++
标志---out绝望。
我知道在 std::exception
中,what()
是虚拟的,这意味着我应该定义它---所以我不确定为什么它应该首先编译,但我对它显然对其他人有用感到沮丧。
我的问题有两个:(1) 问题是什么,为什么对其他人有效? (2,有条件地)C++ 的新手,我还应该问什么是实现 what()
的好方法(假设我必须)以最小的方式,因为我实际上不想传递一个字符串我的例外。我不需要从层次结构的更深层次继承,例如 std::runtime_error
.
根据 C++14 (N3936) [basic.def.odr]/3:
A virtual member function is odr-used if it is not pure.
所以 my_exc1::what()
和 my_exc2::what()
是 odr-used,即使它们从未被调用过。然后我们有 [basic.def.odr]/4:
Every program shall contain exactly one definition of every non-inline function or variable that is odr-used in that program; no diagnostic required.
所以整个程序都有未定义的行为,但不需要 compiler/linker 来诊断它。
这种宽松要求的基本原理是让 link 人的工作更轻松:如果 link 人碰巧能够 link 而无需调用此函数或其他任何内容,那么它就可以这样做; C++ 标准不要求 linker 进行某种整体程序分析以确定是否所有 odr-used 函数都有主体。
所以这段代码有问题,它应该有这两个函数的主体。它还应该有 #include <exception>
。对于编译和执行此代码的人;他们的 iostream
包括 exception
(这是允许的但不是必需的),他们的 link 人将未定义的行为表现为 link 正确。
要提供正文,很简单:
char const *what() const throw() { return ""; }
(假设您可以在线执行)。当然,您可以 return 一些其他固定字符串,例如 "my_exc1"
。请注意,如果您只想 return ""
那么您根本不需要重新声明 what()
。