0

プロジェクトのすべての例外の基本クラスがあります。次のように実装されています。

Exception.hpp

class Exception : public std::exception
{
public:

    ELS_EXPORT_SYMBOL Exception(void) throw();
    ELS_EXPORT_SYMBOL explicit Exception(const std::string& what) throw();
    ELS_EXPORT_SYMBOL Exception(const char* format, ...) throw()
            ELS_PRINTF_FUNC(2, 3);
    ELS_EXPORT_SYMBOL Exception(const Exception& other) throw();
    ELS_EXPORT_SYMBOL Exception& operator =(const Exception& other)
            throw();
    ELS_EXPORT_SYMBOL virtual ~Exception(void) throw();

    ELS_EXPORT_SYMBOL virtual const char* what(void) const throw();

protected:

    ELS_EXPORT_SYMBOL void _M_setWhat(const char* format, ::va_list va)
        throw();

private:

    std::string _M_what;
};

#define ELS_EXC_VA_SET_WHAT(FORMAT)                                         \
    do                                                                      \
    {                                                                       \
        ::va_list va;                                                       \
        ::va_start(va, FORMAT);                                             \
        this->_M_setWhat(FORMAT, va);                                       \
        ::va_end(va);                                                       \
    }                                                                       \
    while (false)

例外.cpp

Exception::Exception(void) throw()
    : std::exception(),
      _M_what("Exception")
{

}

Exception::Exception(const std::string& what) throw()
    : std::exception(),
      _M_what(what.empty() ? "Exception" : what)
{

}

Exception::Exception(const char* format, ...) throw()
    : std::exception(),
      _M_what()
{
    ELS_EXC_VA_SET_WHAT(format);
}

Exception::Exception(const Exception& other) throw()
    : std::exception(other),
      _M_what(other._M_what)
{

}

Exception& Exception::operator =(const Exception& other) throw()
{
    std::exception::operator =(other);
    this->_M_what = other._M_what;
    return *this;
}

Exception::~Exception(void) throw()
{

}

const char* Exception::what(void) const throw()
{
    return this->_M_what.c_str();
}

void Exception::_M_setWhat(const char* format, ::va_list va) throw()
{
    static const size_t BUFSIZE = 512;

    char buf[BUFSIZE];

    ::memset(buf, 0, BUFSIZE);
    ::vsnprintf(buf, BUFSIZE, format, va);
    this->_M_what = std::string(buf);
}

これらのファイルは、次のオプションでコンパイルされた共有ライブラリの一部です。

-Wall -fPIC -O2 -D_GNU_SOURCE -fvisibility=hidden -rdynamic -Wl,-E

ライブラリ自体は問題なくコンパイルされますが、バイナリをコンパイルしてリンクしようとすると、次のエラーが発生します。

Main.cpp:(.text+0x297): undefined reference to `typeinfo for els::except::Exception'

私は少しグーグルで調べましたが、一般的な答えは、すべての仮想メソッドを実装するか、それらを純粋にすることです。ここではこの問題は見られません。私は何を間違っていますか?

4

3 に答える 3

1

OK、これを取得しました - クラス全体を表示する必要があります - クラス ELS_EXPORT_SYMBOL 例外。

于 2013-01-31T21:05:25.813 に答える
0

.so ファイルが C++ 標準ライブラリと静的にリンクされている場合、Linux で RTTI を使用すると問題が発生します。ある .so でインスタンス化されたクラスは、別の .so ではイントロスペクションに使用できません。これは、異なる RTTI テーブルがあるためです (静的リンクにより、各 .so には C++ ランタイムの独自のコピーがあるため)。

2つのオプションがあります:1.すべてのプログラム部分でC++ランタイムとの動的リンクを使用します(私はこのオプションを使用します)2.既に理解したようにクラスを明示的に公開します(多くのクラスがあると面倒になります)

于 2013-01-31T22:56:12.193 に答える
0

ライブラリ自体は問題なくコンパイルできますが、バイナリをコンパイルしてリンクしようとすると、次のエラーが発生します。

リンクコマンドラインとは何ですか?

おそらく、ライブラリを渡すのが早すぎるため、その定義が必要になる前にリンカが既に処理していると考えているでしょう。

于 2013-01-31T20:53:22.337 に答える