English 中文(简体)
不需要重新编译源代码,扩展抽象基类?
原标题:
  • 时间:2009-02-27 23:22:47
  •  标签:

忽略这个,我想到了一个涉及头文件生成的解决方法。虽然不是最好的解决方案,但它可以工作。这个问题太奇怪了,不容易理解。基本上,我想调用一个在库或动态链接库中未声明的虚函数并像正常情况下一样使用它(但是让它没有实现/空的功能)。

我在我的库中有一个抽象基类。所有我的插件都从这个基类继承,用户插件从这个类继承,并且他的应用程序将这个类用作插件指针。我希望用户能够扩展这个类并添加他的特殊函数。问题是,如果他添加了一个虚函数并尝试调用它,由于我的对象没有额外的数据在其虚函数指针表中,代码将会崩溃。我该如何解决这个问题?我曾考虑过继承它,但这会导致当第三个用户进入时出现丑陋的问题。我不希望他们进行强制类型转换以发送扩展函数。

我在思考一个像intptr_t sendMsg(enum msgName, void* argv)这样的消息函数,但是这会降低安全性,而且我需要强制转换所有东西。有什么最佳解决方案吗?我更愿意使用虚函数表,而不是使用sendMsg函数。我该如何解决这个问题?

最佳回答

你是在问是否可以在不重新编译的情况下向基类添加虚函数吗?简短的答案是“不能”。长答案在你的问题中,你必须提供某种通用的“call_func”接口,以允许你“动态地”调用函数。

问题回答

我认为你可以使用注册和回调机制

Your plugin can provide Abstract base class "Base" and function

Register(Base *);

现在客户端可以调用插件的注册函数。

Register(b);

“b” 的定义为

Base *b = new Derived;

其中Derived是从Base派生出的新类。

I am not 100% sure I see the problem.
If the user1 derived type extends your base class (with more virtual methods) then that should be fine (of course your code will never know or understand these new methods but presumably you would not be calling them:

class B
{
    virtual void doStuff() { /* Nothing */}
};

// User 1 version:
class U1: public B
{
     virtual void doStuff()
     {
         this->doA();
         this->doB();
     }
     virtual void doA()  {}
     virtual void doB()  {}
};

// User 2 version can extend it differently.

Note:
If you are worried by slicing because you are storing objects in a vector that is a slightly different problem.

std::vector<B>   objs;
objs.push_back(U1());

std::for_each(objs.begin(),objs.end(),std::mem_fun_ref(&B::doStuff));

这里的问题在于用户定义类型U1无法被复制到向量中,因为向量只保存B对象。这会削减U1中持有的额外数据。

解决此问题的方法是您需要在向量中持有指针。当然,这会带来其他异常安全性方面的问题。因此,boost拥有ptr_vector<>容器,以正确地持有对象,但仍能像对象一样使用它们。

 #include <boost/ptr_container/ptr_vector.hpp>

 ......

boost::ptr_vector<B>   objs;
objs.push_back(new U1());

std::for_each(objs.begin(),objs.end(),std::mem_fun_ref(&B::doStuff));




相关问题
热门标签