Как dllexport класс, производный от std::runtime_error?

#c #windows #exception #dll #dllexport

#c #Windows #исключение #dll #dllexport

Вопрос:

Я настроил библиотеку, предоставляющую класс исключений, производный от стандартного исключения:

 #include <stdexcept>
#include <string>

class BaseException : public std::runtime_error
{
    public:
        BaseException( std::string const amp; msg );
};
  

Пока все хорошо. Довольно хорошо компилируется и обрабатывается в Unix. Теперь я готовлю это для компиляции в Windows DLL:

 #ifdef WIN32
#define MY_EXPORT __declspec(dllexport)
#else
#define MY_EXPORT
#endif

#include <stdexcept>
#include <string>

class MY_EXPORT BaseException : public std::runtime_error
{
    public:
        BaseException( std::string const amp; msg );
};
  

Однако это выдает мне предупреждение C4275: non – DLL-interface class 'std::runtime_error' used as base for DLL-interface class 'BaseException' .

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

Кто-нибудь из вас может меня просветить? Я мог бы просто удалить базовый класс, но тогда перехват std::runtime_error или std::exception не перехват моего пользовательского класса исключений, и я бы очень предпочел, чтобы это было возможно. Итак …?

Ответ №1:

В подобной ситуации для вас есть несколько вариантов.

  1. Экспортируйте его.
  2. Игнорируйте это.
  3. Встроить его.

Важно иметь в виду, что «правильный» способ экспортировать класс из библиотеки DLL — экспортировать весь класс, включая базы и члены. По этой причине существует несколько методов, таких как этот в CodeProject, которые используют «интерфейс» и соответствующую фабрику для создания класса (и соответствующего уничтожения).

Это не слишком полезно для вас в этой ситуации, попытка экспорта std::runtime_error , вероятно, требует больше усилий и, вероятно, приведет к еще большим проблемам позже.

Взято с сайта Microsoft Connect здесь (webarchive), семейство этих ошибок по сути являются шумом;

Я рекомендую избегать этого в первую очередь — размещение типов STL в интерфейсе вашей DLL заставляет вас играть по правилам STL (в частности, вы не можете смешивать разные основные версии VC, и ваши настройки IDL должны совпадать). Однако есть обходной путь. C4251 — это, по сути, шум, и его можно отключить…

Стефан Т. Лававей (один из сопровождающих библиотеки Micrsoft для C ).

Пока параметры компилятора согласованы в проекте, просто отключить это предупреждение должно быть просто отлично.

Последний вариант — определить BaseException класс встроенным и вообще не экспортировать его.

По моему опыту, встроенный вариант почти всегда оказывался самым простым для классов исключений.


Изменения в среде выполнения C для VS2015 привели к изменениям в экспорте std::exception (он не экспортируется из среды выполнения).

Встроенный вариант теперь кажется наиболее подходящим на данный момент (ваш пробег может отличаться).

 class Exception : exception {
public:
    char const* what() const override;
};

inline char const* Exception::what() const {
    /*...*/
};
  

Комментарии:

1. @DevSolar В значительной степени, просто помните, чтобы не изменять параметры компилятора и определения, связанные со стандартной библиотекой (отладка итератора и т.д.), И все должно быть в порядке.

2. И действительно, это так, хотя std::runtime_error этого нет. Да, Microsoft облажалась с этим. (Я предпочитаю выводить off std::runtime_error из-за char const * конструктора, который std::exception отсутствует и который намного упрощает работу. Я знаю, почему я предпочитаю избегать кодирования в Windows …)

3. Ссылка Microsoft connect ведет на страницу входа, а не на что-то полезное.

4. @sqeaky. Я попытаюсь найти общедоступную видимую версию, если у вас есть live.com или outlook.com и т.д. учетная запись, вы можете использовать это. Ключевой бит — это заключенная в кавычки часть в ответе. Не комментируйте выше изменения в VS2015.

5. @Sqeaky. Похоже, что исходная проблема была удалена, это было для VS2010, поэтому я не так уж удивлен. Я нашел ссылку на веб-архив и добавил ее также.