我一直在为lib编写一些代码,并尝试使用默认的Win32控制台应用程序来运行所有内容。由于我已经完成了所有类,我想将所有内容提取到DLL中,因此我开始使用通常的宏进行调整:
#ifdef MYLIB_EXPORTS
#define DllExport __declspec(dllexport)
#else
#define DllExport __declspec(dllimport)
#endif
我在我的代码中使用了一个接口,其定义如下:
__interface DllExport ISerializable {
void Serialize(/* ... */);
/* some other methods */
};
这在我的exe中提供此代码时起作用了。在DLL中,我在编译期间收到错误
error C2039: '=' : is not a member of 'MyLib::ISerializable'
error C2664: 'MyLib::DerivedClass::operator =' : cannot convert parameter 1 from 'const MyLib::ISerializable' to 'const MyLib::DerivedClass &'
为每个继承ISerializable
的类实现所需的方法。 (我使用std::shared_ptr<ISerializable>
几次在我的代码中使用抽象。)然而,当我将__interface
更改为class
并使所有方法都是纯虚拟的时,我不会收到此错误并且编译成功
为什么会出现此错误?为什么我的DLL中的类/接口需要赋值运算符?有没有解决方法?
(在Windows 8 RTM和C ++ 11上使用Visual Studio 2012 RTM。)
以下是发生此错误的一个段(错误始终指向该类的最后一个}
):
class DllExport Tile final : public ISerializable {
public:
__declspec(property(get=GetIsPassable, put=SetIsPassable))
bool IsPassable;
__declspec(property(get=GetTileId, put=SetTileId))
uint16_t TileId;
bool& GetIsPassable() { return this->_IsPassable; }
void SetIsPassable(bool val) { this->_IsPassable = val; }
uint16_t& GetTileId() { return this->_TileId; }
void SetTileId(uint16_t val) { this->_TileId = val; }
bool _IsPassable;
uint16_t _TileId;
void Serialize(OutputFileStream& ofs);
size_t TellSize();
size_t Unserialize(InputFileStream& ifs, size_t metadata = 0);
};
在我使用Tile
类的std::shared_ptr<ISerializable>
类中使用{{1}}的属性的类中也会出现此错误。
答案 0 :(得分:1)
我猜接口没有编译器生成的复制构造函数或赋值运算符。
一种可能的解决方案是明确实施DerivedClass::operator=
。那是因为编译器生成的版本将尝试调用不存在的ISerializable::operator=
。复制构造函数也是一样。
另一个解决方案是使所有类都成为COM类:)
示例强>
使用你的Tile类:
class DllExport Tile final : public ISerializable {
public:
Tile(const Tile& tile) :
_IsPassable(tile._IsPassable), _TileId(tile._TileId)
{
}
/* New Code START */
Tile& operator=(const Tile& tile)
{
_IsPassable = tile._IsPassable;
_TileId = tile._TileId;
return *this;
}
/* New Code END */
__declspec(property(get=GetIsPassable, put=SetIsPassable))
bool IsPassable;
__declspec(property(get=GetTileId, put=SetTileId))
uint16_t TileId;
bool& GetIsPassable() { return this->_IsPassable; }
void SetIsPassable(bool val) { this->_IsPassable = val; }
uint16_t& GetTileId() { return this->_TileId; }
void SetTileId(uint16_t val) { this->_TileId = val; }
bool _IsPassable;
uint16_t _TileId;
void Serialize(OutputFileStream& ofs);
size_t TellSize();
size_t Unserialize(InputFileStream& ifs, size_t metadata = 0);
};