gpt4 book ai didi

c++ - 从 std::exception 继承的提升示例代码不链接

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:17:07 29 4
gpt4 key购买 nike

本文来自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

我在其他地方看到过相同的技术,这向我建议这应该静默编译(和链接)。 (作为示例,我引用了 Anthony Williams C++ Concurrency in Action 第 45 页,他从 std::exception 继承了线程安全堆栈示例的 empty_stack。)

我试过#include <exception>尽管这不是 C++ 库问题,但我什至尝试了 -lstdc++听从有类似问题的人的建议——出于绝望。

我了解 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.

所以整个程序都有未定义的行为,但编译器/链接器不需要对其进行诊断。

这种宽松要求的基本原理是使链接器的工作更容易:如果链接器恰好能够链接而不包括对该函数或其他任何内容的调用,那么它就可以这样做; C++ 标准不要求链接器进行某种整体程序分析以确定是否所有 odr-used 函数都有主体。


所以这段代码有问题,它应该有这两个函数的主体。它还应该有 #include <exception> .对于编译和执行此代码的人;他们的 iostream包括 exception (这是允许的,但不是必需的),并且他们的链接器将未定义的行为表现为链接正确。


要提供一个主体,它很简单:

char const *what() const throw() { return ""; }

(假设您可以在线执行)。当然,您可以返回一些其他固定字符串,例如 "my_exc1" .请注意,如果您只想返回 ""那么你不需要重新声明 what()完全没有。

关于c++ - 从 std::exception 继承的提升示例代码不链接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32031406/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com