Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/131.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ LNK4217对从抽象DLL接口类派生的类发出警告_C++ - Fatal编程技术网

C++ LNK4217对从抽象DLL接口类派生的类发出警告

C++ LNK4217对从抽象DLL接口类派生的类发出警告,c++,C++,编译两个类时,我收到LNK4217警告:一个是定义抽象接口和静态工厂方法,该方法将返回实现该接口的对象。此类通过\uuu declspec(dllexport)导出。另一个类实现该接口。下面是一个复制警告的简化示例: PublicAPI.h #pragma once #include <memory> #ifdef PublicAPI_Exports #define API_EXP __declspec (dllexport) #else #define API_EXP __de

编译两个类时,我收到LNK4217警告:一个是定义抽象接口和静态工厂方法,该方法将返回实现该接口的对象。此类通过
\uuu declspec(dllexport)
导出。另一个类实现该接口。下面是一个复制警告的简化示例:

PublicAPI.h

#pragma once

#include <memory>

#ifdef PublicAPI_Exports
#define API_EXP __declspec (dllexport)
#else
#define API_EXP __declspec (dllimport)
#endif

class API_EXP PublicAPI
{
public:
  virtual ~PublicAPI();

  static std::shared_ptr<PublicAPI> init(const char *selection);

  virtual int compute() = 0;

protected:
  PublicAPI();
};
PrivateAPI
被编译成一个静态库,
PublicAPI
被编译成一个DLL,并链接到
PrivateAPI
<代码>PublicAPI_导出在
PublicAPI
项目中定义

我收到的警告是:

3>PrivateAPI.lib(PrivateAPI.obj) : warning LNK4217: locally defined symbol ??1PublicAPI@@UEAA@XZ (public: virtual __cdecl PublicAPI::~PublicAPI(void)) imported in function "public: virtual __cdecl PrivateAPI::~PrivateAPI(void)" (??1PrivateAPI@@UEAA@XZ)
3>PrivateAPI.lib(PrivateAPI.obj) : warning LNK4217: locally defined symbol ??0PublicAPI@@IEAA@XZ (protected: __cdecl PublicAPI::PublicAPI(void)) imported in function "private: __cdecl PrivateAPI::PrivateAPI(void)" (??0PrivateAPI@@AEAA@XZ)

我通读了与此链接器警告相关的和StackOverflow,但我仍然不知道这里到底出了什么问题,也不知道如何正确修复它://

我找到了两种解决方案:

解决方案1(由@HansPassant和imho提供更好/更通用的解决方案)

PublicAPI\u导出
也需要为
PrivateAPI
项目定义,而不仅仅是为
PublicAPI
项目定义

我对原因的理解是:
PrivateAPI
类继承自
PublicAPI
,因此它还包括
PublicAPI.h
PrivateAPI
还“继承”了
PublicAPI
中的dlliport/dllexport定义。但是,
PrivateAPI
被独立编译成一个静态库,之后仅由
PublicAPI
链接。因此,当编译
PrivateAPI
时,未定义
PublicAPI\u Exports
,则
PrivateAPI
类将被定义为
dllimport
(通过
PublicAPI.h
)。当
PublicAPI
项目在定义了
PublicAPI\u Exports
并链接到
PrivateAPI
静态库的情况下生成时,这些定义不匹配并导致此警告。因此,有必要为
PublicAPI
PrivateAPI
项目定义
PublicAPI\u Exports

解决方案2(针对我的特定示例)

似乎我也只能
dllexport
静态
init
函数,该函数创建一个满足
PublicAPI
接口的对象。这需要更改
PublicAPI.h
,如下所示:

#pragma once

#include <memory>

#ifdef PublicAPI_Exports
#define API_EXP __declspec (dllexport)
#else
#define API_EXP __declspec (dllimport)
#endif

class PublicAPI
{
public:
  virtual ~PublicAPI();

  API_EXP static std::shared_ptr<PublicAPI> init(const char *selection);

  virtual int compute() = 0;

protected:
  PublicAPI();
};
#pragma一次
#包括
#ifdef PublicAPI_导出
#定义API EXP declspec(dllexport)
#否则
#定义API EXP declspec(dllimport)
#恩迪夫
公共API类
{
公众:
virtual~PublicAPI();
API_EXP static std::shared_ptr init(const char*selection);
虚拟int compute()=0;
受保护的:
PublicAPI();
};

这是可行的,因为在
PrivateAPI
中不会再次声明静态函数。
init
返回的对象在包含并链接
PublicAPI

的客户机中似乎工作正常(即
compute
函数可访问)。您忘记在构建DLL的项目中定义PublicAPI\u Exports宏。因此链接器会看到两个定义,一个是dllimport,另一个在.cpp文件中。这违反了ODR。右键单击项目>属性>C/C++>预处理器>“预处理器定义”设置。添加PublicAPI_导出。@HansPassant PublicAPI_导出是在PublicAPI项目中定义的(如上所述)-我只是仔细检查了一下。链接器不是这么说的。确保为所有配置和所有平台定义了它。请记住,对于您链接的静态库,它很容易被忽略。好的,在PrivateAPI项目中另外定义PublicAPI_Exports宏可以解决此警告。为了确保我正确理解了背后的原因:PrivateAPI包含PublicAPI头来定义从PublicAPI继承的类。因此,在将PrivateAPI编译成静态库时,我们必须确保在PublicAPI头中定义了dllexport,因为后来PublicAPI(也定义了dllexport)链接到PrivateAPI静态库,导出定义必须匹配!?
#include "PrivateAPI.h"

PrivateAPI::PrivateAPI() {}

PrivateAPI::PrivateAPI(std::string selection)
{
  // init members based on selection
}

PrivateAPI::~PrivateAPI() {}

int PrivateAPI::compute()
{
  return 42;
}
3>PrivateAPI.lib(PrivateAPI.obj) : warning LNK4217: locally defined symbol ??1PublicAPI@@UEAA@XZ (public: virtual __cdecl PublicAPI::~PublicAPI(void)) imported in function "public: virtual __cdecl PrivateAPI::~PrivateAPI(void)" (??1PrivateAPI@@UEAA@XZ)
3>PrivateAPI.lib(PrivateAPI.obj) : warning LNK4217: locally defined symbol ??0PublicAPI@@IEAA@XZ (protected: __cdecl PublicAPI::PublicAPI(void)) imported in function "private: __cdecl PrivateAPI::PrivateAPI(void)" (??0PrivateAPI@@AEAA@XZ)
#pragma once

#include <memory>

#ifdef PublicAPI_Exports
#define API_EXP __declspec (dllexport)
#else
#define API_EXP __declspec (dllimport)
#endif

class PublicAPI
{
public:
  virtual ~PublicAPI();

  API_EXP static std::shared_ptr<PublicAPI> init(const char *selection);

  virtual int compute() = 0;

protected:
  PublicAPI();
};