私の質問は、STLを内部に持つC++クラスのエクスポートに関連しています。例えば:
class __declspec(dllexport) Hello
{
std::string name;
public:
std::string& getName();
void setName(const std::string& name);
}
さまざまな記事がこれが非常に悪いことを示しているようで、それは非常に理解できます。すべてが同じコンパイラ設定とCRTバージョンでコンパイルされる必要があります。そうしないと、すべてがクラッシュして燃えます。
質問:
私が理解していないのは、なぜデータメンバーだけが問題を抱えているように見えるのかということです。以下のコードで、次のようになります。 " C4251:クラスのクライアントが使用するにはdll-interfaceが必要です"; これは、インスタンス化されたstd :: string:をエクスポートすることで明らかに修正されています。
struct __declspec(dllexport) SomeClass
{
// Removes the warning?
// http://www.unknownroad.com/rtfm/VisualStudio/warningC4251.html
// template class __declspec(dllexport) std::string;
std::string name; // Compiler balks at this
}
そして、修正されたバージョンは次のとおりです。
// Export the instantiations of allocator and basic_string
template class __declspec(dllexport) std::allocator<char>;
template class __declspec(dllexport) std::basic_string<char, std::char_traits<char>, std::allocator<char> >;
struct __declspec(dllexport) SomeClass
{
std::string name; // No more balking!
}
(これにより、DLLを使用しようとすると、LNK2005に「basic_stringがすでに定義されています」が表示されます。つまり、クライアントのCRTにリンクする必要がないため、DLLのインスタンス化を使用することになります)。
戻り値の型と引数はSTLに問題がないようであり、コンパイラーからメンバーが取得するのと同じ処理データを受け取りません。
// No exporting required?
struct __declspec(dllexport) SomeOtherClass
{
std::string doSomething1(); // No problemo
void doSomething2(const std::string& s); // No problemo
}
追加情報(質問は上にあります)
両者に:
class A {
std::string foo() { return std::string(); }
// std::string& foo(); gives the same result!
// std::string* foo(); also gives the same result!
}
class B {
std::string a;
}
std::basic_stringもstd::allocatorもエクスポートしていないようです。むしろ、クラスのメンバー/関数のみをエクスポートします。
ただし、質問で言及されている修正バージョンは、basic_stringとallocatorの両方をエクスポートします。