4

我一直在为 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>在我的代码中使用了几次抽象。)但是,当我更改__interfaceclass并使所有方法成为纯虚拟方法时,我没有收到此错误并且编译成功。

为什么我会收到此错误?为什么我的 DLL 中的类/接口需要赋值运算符?有什么解决方法吗?

(在带有 C++11 的 Windows 8 RTM 上使用 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>.

4

1 回答 1

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); 
}; 
于 2012-09-16T21:37:44.497 回答