24

It is not a good practice using stl-classes in the dll-interface as Common practice in dealing with warning c4251: class … needs to have dll-interface explains. An example is given:

#include <iostream>
#include <string>
#include <vector>


class __declspec(dllexport) HelloWorld
{
public:
    HelloWorld()
    {
        abc.resize(5);
        for(int i=0; i<5; i++)
            abc[i] = i*10;

        str="hello the world";
    }
    ~HelloWorld()
    {

    }

    std::vector<int> abc;
    std::string str;

};

When compiling this file, the following warnings can be observed:

 warning C4251: 'HelloWorld::str' : class 'std::basic_string<_Elem,_Traits,_Ax>' needs to have dll-interface to be used by clients of class 'HelloWorld'    
 warning C4251: 'HelloWorld::abc' : class 'std::vector<_Ty>' needs to have dll-interface to be used by clients of class 'HelloWorld'

Then the question is how we can implement the same functionality without using STL class vector and string. One implementation I could think of is as follows:

class __declspec(dllexport) HelloWorld2
{
public:
    HelloWorld2()
    {
         abc_len = 5;
         p_abc = new int [abc_len];
         for(int i=0; i<abc_len; i++)
             p_abc[i] = i*10;

         std::string temp_str("hello_the_world");
         str_len = temp_str.size();
         p_str = new char[str_len+1];
         strcpy(p_str,temp_str.c_str());
    }
    ~HelloWorld2()
    {
        delete []p_abc;
        delete []p_str;
    }

    int *p_abc;
    int abc_len;
    char *p_str;
    int str_len;



};

As you can see, in the new implementation we use int *p_abc to substitute vector abc and char *p_str to replace string str. The question I have is whether there are other elegant implementation approaches that can do the same. Thanks!

4

4 に答える 4

8

ここでどの問題を解決したいのかわかりません。2 つの異なる問題があります。クロス コンパイラ バイナリ互換性と、「未定義シンボル」リンカ エラーの回避です。あなたが引用したC4251警告は、2番目の問題について語っています。std::stringこれは、特にや などの SCL クラスでは、ほとんど問題になりませんstd::vector。それらは CRT に実装されているため、アプリケーションの両側で同じ CRT を使用している限り、すべてが「正常に動作」します。その場合の解決策は、警告を無効にすることです。

あなたがリンクした他のスタックオーバーフローの質問で議論されているものであるクロスコンパイラのバイナリ互換性OTOHは、まったく異なる獣です。それがうまくいくためには、基本的に、すべてのパブリック ヘッダー ファイルに SCL クラスの言及がないようにする必要があります。つまり、すべてを PIMPL するか、あらゆる場所で抽象クラスを使用する (またはその組み合わせ) 必要があります。

于 2016-02-09T07:36:08.853 に答える
8

または、最も簡単な方法で、__declspecエクスポートしたい唯一のメンバーに移動します。

class HelloWorld
{
public:
    __declspec(dllexport) HelloWorld()
    {
        abc.resize(5);
        for(int i=0; i<5; i++)
            abc[i] = i*10;

        str="hello the world";
    }
    __declspec(dllexport) ~HelloWorld()
    {
    }
    std::vector<int> abc;
    std::string str;
};
于 2016-02-08T17:39:52.737 に答える
3

Pointer To Implementation (pImpl)イディオムを使用するだけです。

于 2014-02-26T22:29:14.440 に答える