Повысьте пример кода, наследуемого от std :: exception не связывает

Эта статья из boost: обработка ошибок и исключений выдвигает следующий программный код:

#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

Я видел аналогичную технику, используемую в другом месте, предлагая мне, что это должно скомпилировать (и связать) без вывода сообщений. (В качестве примера я приведу Энтони Уильямса C ++ Параллелизм в действии п. 45, где он наследует std::exception делать empty_stack для примера многопоточного стека.)

Я пытался #include <exception> и несмотря на то, что это не проблема библиотеки C ++, я даже попробовал -lstdc++ флаг по совету людей с похожими проблемами — от отчаяния.

Я понимаю что в std::exception, what() является виртуальным, то есть я должен определить его — поэтому я не уверен, почему он должен компилироваться в первую очередь, но я разочарован тем, что он, очевидно, подходит для других людей.

У меня два вопроса: (1) В чем проблема и почему это работает для других? (2, условно) Новичок в C ++, я должен также спросить, что является хорошим способом реализации what() (при условии, что мне придется) самым минимальным образом, так как я на самом деле не хочу передавать строку с моим исключением. Мне не нужно наследовать от более глубоких в иерархии, таких как std::runtime_error,

2

Решение

Согласно C ++ 14 (N3936) [basic.def.odr] / 3:

Виртуальная функция-член используется odr, если она не является чистой.

Так my_exc1::what() а также my_exc2::what() являются УСО используемый, хотя они никогда не называются. Тогда у нас есть [basic.def.odr] / 4:

Каждая программа должна содержать ровно одно определение каждой не встроенной функции или переменной, которая используется в этой программе в виде odr; Диагностика не требуется.

Таким образом, вся эта программа имеет неопределенное поведение, но компилятор / компоновщик не обязан ее диагностировать.

Обоснование этого слабого требования состоит в том, чтобы упростить работу компоновщика: если компоновщик может ссылаться без включения вызова этой функции или чего-либо еще, то он может это сделать; Стандарт C ++ не требует, чтобы компоновщик выполнял какой-то анализ программы целиком, чтобы определить, все ли УСО используемый функции имеют тела.


Таким образом, этот код содержит ошибки и должен иметь тела для обеих этих функций. Это также должно иметь #include <exception>, Для людей, которые скомпилировали и выполнили этот код; их iostream включены exception (что разрешено, но не обязательно), и их компоновщик проявил неопределенное поведение как появляющееся для правильной ссылки.


Чтобы обеспечить тело это так же просто, как:

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

(при условии, что вы в порядке, делая это в строке). Конечно, вы можете вернуть некоторую другую фиксированную строку, такую ​​как "my_exc1", Обратите внимание, что если вы хотите только вернуться "" тогда вам не нужно повторно объявлять what() совсем.

1

Другие решения


По вопросам рекламы [email protected]