是否可以“复制”模板类派生自非模板化基础的对象?

时间:2012-05-12 00:26:42

标签: c++ class templates polymorphism

我用C ++构建了一个小型,有限范围的跨平台UI库。它使用以下类来处理UI回调:

// Base class for templated __Callback class to allow for passing __Callback
// objects as parameters, storing in containers, etc. (as Callback*)
class Callback
{
    public:
        virtual void execute() = 0;
        virtual ~Callback() { }

    protected:
        Callback() { }
};

正如评论所描述的,这是回调的基类 - 允许将它们作为参数传递并将它们存储在UI小部件中,以便可以执行正确的回调(例如,当用户单击按钮时)。

// C++ has no callbacks (in the sense of an action [method] of a
// target [object]), so we had to roll our own. This class can be used
// directly, but the NEW_CALLBACK macro is easier.
template <class __TargetType>
class __Callback : public Callback
{
    public:
        typedef __TargetType TargetType;
        typedef void (TargetType::*ActionType)(void);

        virtual void execute()
        {
            (this->__target->*this->__action)();
        }

        __Callback(TargetType* target_, ActionType action_) :
        Callback(), __target(target_), __action(action_) { }

        virtual ~__Callback() { }

    private:
        // target object for the callback
        TargetType* __target;

        // action (method) of the target that will be called
        ActionType __action;
};

这个模板化的类是回调范式的核心。它存储指向对象的指针和指向成员函数的指针,以便稍后可以在目标对象上调用成员函数。

#define NEW_CALLBACK(class_, obj_, act_) \
    new __Callback<class_>(obj_, &class_::act_)

这个宏使得创建模板__Callback对象变得容易一些。

这已经很长时间了!带回调的按钮可以实例化为:

MyClass* obj = new MyClass();
Button* btn = new Button("Title", NEW_CALLBACK(MyClass, obj, btnClicked));

这会创建一个按钮,以便稍后放置在窗口或其他容器中,点击后会调用obj->btnClicked()

现在,我的问题(对于冗长的设置感到抱歉,我认为我不能再削减它了)。出现了我需要复制Callback*对象的情况。当然,因为它只是指向基类的指针,所以我无法确定模板化派生类的类型。

如何复制任意Callback对象,副本指向与原始对象相同的目标和操作?或者,这种回调是否存在完全不同的方法我应该采取的问题(虽然我不想改变它太多)?

全部谢谢!

2 个答案:

答案 0 :(得分:3)

我不知道你是否应采取更好的方法,但这似乎是克隆方法的理想用途。

您只需在__Callback模板中定义复制构造函数,在基类中定义纯虚拟Clone方法,然后在模板中实现该虚方法(利用您创建的复制构造函数)< / p>

例如:

class Callback
{
    public:
    ...
    virtual Callback* Clone()=0;
};

template <class __TargetType>
class __Callback : public Callback
{
public:
    ...
    __Callback(const __Callback& other) :
        __target(other.target_), __action(other.action_) { }

    virtual Callback* Clone()
    {
        return new __Callback(this);
    }
}

答案 1 :(得分:1)

使用clone替代虚拟构造函数。请注意 共同变量返回类型,使其真正起作用。 e.g。

struct Callback {
  virtual Callback* clone() const;
};

template<...>
struct Callback_impl {
  virtual Callback_impl* clone() const;
};

您还应该考虑shared_ptr进行终身管理。所有 这似乎有点脆弱。

对我来说,看起来你想要std::function。它是多态的,类型安全的,并通过std::mem_fn使用指向成员函数的指针。