C++ 在Visual Studio 2013中获取std::string方法和运算符的错误LNK2005

C++ 在Visual Studio 2013中获取std::string方法和运算符的错误LNK2005,c++,visual-studio-2013,stdstring,C++,Visual Studio 2013,Stdstring,我有一个基于Qt的项目,我已经构建和使用visualstudio2008大约5年了。我构建并使用“调试”和“发布”构建配置 我正在迁移到VS2013,现在我在std::string方法和运算符上遇到了一些非常奇怪的LNK2005错误 代码库分为两个库和一组UI目录。在调试生成配置中,这两个库内置到DLL中,然后在运行其中一个UI时必须在路径中指定。在发布模式下,所有内容都静态编译为单个可执行文件。效果很好 这两个库是“model”和“engine”。首先建立“模型”,然后建立“引擎”。“引擎”使

我有一个基于Qt的项目,我已经构建和使用visualstudio2008大约5年了。我构建并使用“调试”和“发布”构建配置

我正在迁移到VS2013,现在我在std::string方法和运算符上遇到了一些非常奇怪的LNK2005错误

代码库分为两个库和一组UI目录。在调试生成配置中,这两个库内置到DLL中,然后在运行其中一个UI时必须在路径中指定。在发布模式下,所有内容都静态编译为单个可执行文件。效果很好

这两个库是“model”和“engine”。首先建立“模型”,然后建立“引擎”。“引擎”使用“模型”(库)

当“引擎”被链接时,我会得到一系列以下错误,所有这些错误都与std::string有关:

    1>model.lib(model.dll) : error LNK2005: "public: class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > 
        & __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::operator=(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" 
        (??4?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAEAAV01@ABV01@@Z) 
        already defined in NamedObject.obj

    1>model.lib(model.dll) : error LNK2005: "public:
        int __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::compare(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)const " 
        (?compare@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QBEHABV12@@Z) 
        already defined in NamedObject.obj
还有许多其他类似的LNK2005错误,但这一个是相当孤立的一个小类

我检查/验证的事项:

  • 在本例中,我使用一致的“/Mxx”编译器选项(/MDd)编译和链接
  • “-Zc:wchar\u t”选项在“model”和“engine”的makefile中都指定
  • 两个库都与“/NOLOGO/DYNAMICBASE/NXCOMPAT/DEBUG/NODEFAULTLIB:LIBCMT/NODEFAULTLIB:LIBCPMT/NODEFAULTLIB:LIBCMTD/NODEFAULTLIB:LIBCPMTD/NODEFAULTLIB:MSVCRT/NODEFAULTLIB:MSVCPRT/MSVCPRT/DLL”链接
  • 各种对象文件上的“dumpbin/dependencies”显示“/DEFAULTLIB:msvcprtd/DEFAULTLIB:msvctd/DEFAULTLIB:OLDNAMES”
我是。卡住了

编辑。更多细节。我在两个版本(VS2008和VS2013)上都做了dumpbin/all model.dll,发现VS2013版本确实包含std::string实现:
?4?$basic_string@DU?$char_traits@D@性病病毒$allocator@D@2@@std@@QAEAAV01@PBD@Z(public:class std::basic_string&uu thiscall std::basic_string::operator=(char const*))

但是VS2008版本没有

编辑2好吧,我决定尝试一下。。。。。我已经将它隔离为几个小类(是的,所有的东西都是用相同版本的编译器、相同的VS解决方案等编译的)

下面是我对一个简单的“model”类的声明。我稍后会解释一些事情。您可以大致了解这些方法的实现

# pragma once 
# if defined(WIN32) && defined(BUILD_DLL)
#     if defined(MODEL_EXPORT_API) // inside DLL
#         define MODEL_EXPORTAPI __declspec(dllexport)
#         define MODEL_EXPIMP_TEMPLATE
#     else // outside DLL
#         define MODEL_EXPORTAPI __declspec(dllimport)
#         define MODEL_EXPIMP_TEMPLATE extern
#     endif
# else
#     define MODEL_EXPORTAPI
# endif

# include <string>
# if defined (WIN32)
    MODEL_EXPIMP_TEMPLATE template class MODEL_EXPORTAPI std::basic_string<char, std::char_traits<char>, std::allocator<char> >;
# endif

namespace model { namespace exceptions {
    class MODEL_EXPORTAPI FlowException {
    public:
        FlowException(const std::string & m);
        virtual ~FlowException();
        virtual const char *  what() const;
    private:
         // Copy constructor and assignment operator are private and
        // unimplemented.
        FlowException(const FlowException &);
        FlowException &    operator=(const FlowException &);

        std::string _msg;
   };
} }
#pragma一次
#如果已定义(WIN32)和已定义(BUILD_DLL)&&D
#如果已定义(模型导出API)//在DLL内部
#定义模型\u EXPORTAPI\u declspec(dllexport)
#定义模型导出模板
#else//外部DLL
#定义模型导出API declspec(dllimport)
#定义模型EXPIMP模板extern
#恩迪夫
#否则
#定义模型\导出API
#恩迪夫
#包括
#如果已定义(WIN32)
MODEL_EXPIMP_TEMPLATE模板类MODEL_EXPORTAPI std::basic_字符串;
#恩迪夫
命名空间模型{命名空间异常{
类模型\u导出API流异常{
公众:
FlowException(const std::string&m);
虚拟~FlowException();
虚拟常量char*what()常量;
私人:
//复制构造函数和赋值运算符是私有的且
//未执行。
FlowException(常量FlowException&);
FlowException&运算符=(常量FlowException&);
std::string\u msg;
};
} }
对于“引擎”类。这个类似于上面的“model”类。再一次,你可以用figger计算出它的实现是什么

# pragma once

# include <string>

# if    defined(WIN32) && defined(BUILD_DLL)
#    if defined(FLOWENGINE_EXPORT_API) // inside DLL
#       define FLOWENGINE_EXPORTAPI   __declspec(dllexport)
#       define FLOWENGINE_EXPIMP_TEMPLATE
#    else // outside DLL
#       define FLOWENGINE_EXPORTAPI   __declspec(dllimport)
#       define FLOWENGINE_EXPIMP_TEMPLATE extern
#    endif
# else
#    define FLOWENGINE_EXPORTAPI
# endif

namespace flowEngine { namespace core {

class NamedObject {
public:
    NamedObject(const std::string & n);

    virtual ~NamedObject();

    bool        operator== (const NamedObject & v) const;

    const char *    getName() const;

private:
    // Copy constructor and assignment operator are private and
    // unimplemented.
    NamedObject(const NamedObject &);
    NamedObject &   operator=(const NamedObject &);

    std::string     _name;
};
} }
#pragma一次
#包括
#如果已定义(WIN32)和已定义(BUILD_DLL)&&D
#如果已定义(FLOWENGINE\u EXPORT\u API)//在DLL内部
#定义FLOWENGINE\u EXPORTAPI\u declspec(dllexport)
#定义FLOWENGINE_EXPIMP_模板
#else//外部DLL
#定义FLOWENGINE\u EXPORTAPI\u declspec(dllimport)
#定义FLOWENGINE\u EXPIMP\u模板外部
#恩迪夫
#否则
#定义FLOWENGINE\u导出API
#恩迪夫
命名空间流引擎{命名空间核心{
类名对象{
公众:
NamedObject(const std::string&n);
虚拟~NamedObject();
布尔运算符==(常量NamedObject&v)常量;
常量char*getName()常量;
私人:
//复制构造函数和赋值运算符是私有的且
//未执行。
NamedObject(const NamedObject&);
NamedObject&运算符=(const NamedObject&);
std::string _name;
};
} }
现在进行测试

  • 如果在“MODEL exception”类中没有“MODEL\u EXPIMP\u TEMPLATE TEMPLATE class…”行,则会得到“warning C4251:‘MODEL::exceptions::FlowException::_msg:‘class’std::basic_string,std::allocator>'需要有dll接口,以便“model::exceptions::FlowException”类的客户端在该头文件的每个引用和此示例链接上使用

  • 如果我将模型中的“exception”类“包括”到引擎中的一个类中,并且不使用“model_EXPIMP_TEMPLATE class…”行,则此示例有效(两个库链接)

  • 如果我将模型中的“exception”类包含到引擎中的类中,并在exception类中使用“model_EXPIMP_TEMPLATE TEMPLATE class…”行,则当引擎库链接到:“1>model.lib(model.dll)时,此示例将失败:错误LNK2005:“public:uu thiscall std::basic_string,class std::allocator>::basic_ustring,class std::allocator>(char const*)”(?0?$basic)_string@DU?$char_traits@D@性病病毒$allocator@D@2@@std@@QAE@PBD@Z) 已在NamedObject.obj'中定义


  • 现在怎么办?在一个例子中,编译器告诉我修复代码,当我链接失败时……

    我正在迁移到VS2013,现在我在std::string方法和运算符上遇到一些非常奇怪的LNK2005错误。您是否对所有依赖项(包括Qt)都使用VS2013?是的。我已经使用VS2013重建了Qt。你确定要链接VS2013 CRT吗?编辑:等等,我看到你在
    # pragma once
    
    # include <string>
    
    # if    defined(WIN32) && defined(BUILD_DLL)
    #    if defined(FLOWENGINE_EXPORT_API) // inside DLL
    #       define FLOWENGINE_EXPORTAPI   __declspec(dllexport)
    #       define FLOWENGINE_EXPIMP_TEMPLATE
    #    else // outside DLL
    #       define FLOWENGINE_EXPORTAPI   __declspec(dllimport)
    #       define FLOWENGINE_EXPIMP_TEMPLATE extern
    #    endif
    # else
    #    define FLOWENGINE_EXPORTAPI
    # endif
    
    namespace flowEngine { namespace core {
    
    class NamedObject {
    public:
        NamedObject(const std::string & n);
    
        virtual ~NamedObject();
    
        bool        operator== (const NamedObject & v) const;
    
        const char *    getName() const;
    
    private:
        // Copy constructor and assignment operator are private and
        // unimplemented.
        NamedObject(const NamedObject &);
        NamedObject &   operator=(const NamedObject &);
    
        std::string     _name;
    };
    } }