2009-12-28 83 views
2

在我的公司系统中,我们使用一个类来表示bean。它只是使用boost :: variant和一些序列化/反序列化的信息的持有者。它运行良好,但我们遇到了一个问题:它不在接口之上,并且由于我们通过dll使用模块化,为它构建接口变得非常复杂,因为它几乎被应用程序的每个部分所使用,并且可悲地接口(抽象类)必须通过指针访问,巫婆几乎不可能重构整个系统。Turn class“Interfaceable”

我们的结构是:

DLL答:通过抽象类
DLL接口B定义:接口实现

有一种无痛的方式来实现这一目标(可能使用模板,我不知道)或者我应该忘记做这个工作,并简单地链接所有与DLL B?

谢谢

编辑:这是我的例子。
这是在dll上A
BeanProtocol是N dataprotocol itens的持有者,它由索引处理。

class DataProtocol; 

class UTILS_EXPORT BeanProtocol 
{ 
public: 
    virtual DataProtocol& get(const unsigned int ) const 
    { 
    throw std::runtime_error("Not implemented"); 
    } 

    virtual void getFields(std::list<unsigned int>&) const 
    { 
    throw std::runtime_error("Not implemented"); 
    } 

    virtual DataProtocol& operator[](const unsigned int) 
    { 
    throw std::runtime_error("Not implemented"); 
    } 

    virtual DataProtocol& operator[](const unsigned int) const 
    { 
    throw std::runtime_error("Not implemented"); 
    } 

    virtual void fromString(const std::string&) 
    { 
    throw std::runtime_error("Not implemented"); 
    } 

    virtual std::string toString() const 
    { 
    throw std::runtime_error("Not implemented"); 
    } 

    virtual void fromBinary(const std::string&) 
    { 
    throw std::runtime_error("Not implemented"); 
    } 

    virtual std::string toBinary() const 
    { 
    throw std::runtime_error("Not implemented"); 
    } 

    virtual BeanProtocol& operator=(const BeanProtocol&) 
    { 
    throw std::runtime_error("Not implemented"); 
    } 

    virtual bool operator==(const BeanProtocol&) const 
    { 
    throw std::runtime_error("Not implemented"); 
    } 

    virtual bool operator!=(const BeanProtocol&) const 
    { 
    throw std::runtime_error("Not implemented"); 
    } 

    virtual bool operator==(const char*) const 
    { 
    throw std::runtime_error("Not implemented"); 
    } 

    virtual bool hasKey(unsigned int field) const 
    { 
    throw std::runtime_error("Not implemented"); 
    } 
}; 

其他类(名为GenericBean)实现它。这是我发现这个工作的唯一方法,但是现在我想将它转换为一个真正的接口并删除UTILS_EXPORT(这是一个_declspec宏),最后删除B与A的强制关联。

+0

你可以添加一些示例代码?真的很难判断你的问题到底是什么。 – 2009-12-28 16:23:21

+0

我不明白,一个抽象类的DLL?没有代码。 – 2009-12-28 16:30:53

+0

为什么使用异常而不是纯虚拟方法? – 2010-01-06 05:20:28

回答

0

DLL答:通过抽象类的接口定义

DLL B:接口实现

你能解释一下你的接口implementaion是什么意思?在理想的情况下,接口应该不过是简单的标题。即使你有一些默认的实现,链接它们是否有很大的负担?

您所描述的实质上是一种插件体系结构。恐怕有没有干净的方式通过DLL来做到这一点。

当然,如果你只在Windows上,你可以创建COM类(简单)或查找__declexport关键字。

是的,使用dll时,我会远离模板 - 它们通常会造成比它们更大的麻烦。

+0

-1,错了。 DLL A将创建一个vptr表,DLL B将创建第二个vptr表,并且这些类将不兼容。 – Joshua 2009-12-28 16:37:29

+0

@Joshua:我不确定你指的是我的帖子的哪一部分。 – dirkgently 2009-12-28 16:41:31

+0

由于DLL的工作方式,关于“mere headers”的部分会导致vtable问题。 – Joshua 2009-12-28 17:44:17

0

如果我记得你必须在DLL A中实现第一个列出的构造函数,并用.DEF文件中的exports表导出该构造函数和VTABLE。

0

老实说,我真的不明白你在做什么,看起来你对“界面”有不同的理解,因为你使用DLL来“存储”基础(界面/核心/等等)和你所谓的“接口”有“实现”!如果你现有的解决方案没有围绕接口构建,那么如果你引入它们,它将需要重新编译,很可能没有从管理的角度去看待(除非你的经理也是技术怪杰)。

0

看,我可能完全不在这里,因为我在理解你的问题时有点麻烦。但是,如果我是正确的,您想要删除A和B之间的强制关联。

您有接口类,它具有所有纯虚拟方法。您的应用程序使用此类型的指针与具体对象进行通信。

您的DLL实现了抽象类,保持DLL中的所有内存分配和销毁。

您在DLL中创建了一个工厂函数,它返回一个抽象类型的指针,但它是否实际实例化了一个具体对象。工厂函数需要导出到DLL中,没有别的。

现在,您可以在运行时链接到dll,调用工厂函数并实例化对象。

难道你喜欢什么?

+0

这是我想要做的,但问题只是在我的系统上我没有作为指针访问它(因为它们不是纯虚拟的),我无法做到这一点,因为重构将是疯狂的。 – scooterman 2010-03-19 14:32:06

1

我不完全确定你的意思,但如果问题是BeanProtocol不是一个指针,那么你不能让它包装一个指向另一个类的指针(比如BeanPointerImpl),然后你可以从你的DLL。

class BeanProtocol 
{ 
    private BeanProtocolImpl m_impl; 
    public: 
    DataProtocol& get(const unsigned int index) const 
    { 
    if(! m_impl) 
    { 
     load_impl(get_appropriate_dll()) 
    } 
    return m_impl->get(index); 
    } 

...等等BeanProtocol上的所有其他方法。

然后你可以实现你的插件BeanProtocolImpl为不同的子类,从您的DLL(DLL中的B这种情况下)导出它们和废料DLL A.

在这个例子中,我假设load_impl负荷DLL,调用工厂方法来获取BeanProtocolImpl的实现并将其存储在m_impl中,如果加载失败则抛出异常。

当然,您需要重新编译整个应用程序,但不能重构它。