通用对象包装器

博尔迪诺

我想知道是否存在一种好的通用方法来编写对象包装器,这样您就可以调用包装在包装器类本身上的类定义的所有方法(而不必在包装器类中显式重新定义类接口)。例如,两个不同的任意类:

class InnerExample1 {
public:
    InnerExample1(int a, bool b) {...}
    void DoSomething1(int a) {...}
    bool DoSomething2(bool b) {...}
    etc...
};

class InnerExample2 {
    InnerExample2(float a, int b) {...}
    void DoWork(int a) {...}
    bool GetResult(bool b) {...}
    etc...
};

我想要一个通用定义的包装器类,这样我可以做:

Wrapper<InnerExample1> inner1;
inner1.DoSomething(42);
bool result = inner1.DoSomething2(false);

Wrapper<InnerExample2> inner2;
inner2.DoWork(21);
bool result = inner2.GetResult(true);

由于“包装器”具有足够的通用性,因此能够处理任一包装器并将所有对其进行的调用转发给其内部委托。

我已经看到了诸如工厂模式之类的代码,在工厂模式中,使用可变参数args,泛型工厂可以实例化任何类,以及泛化对单个成员方法的绑定,但是对于整个类而言,却没有做完。在我看来,这是不可能的……但是SO的人们想出了我从未拥有过的各种东西:)

编辑:我试图通过省略不必要的细节来简化问题,但我遗漏了太多。我需要包装器在每个调用周围插入一些逻辑。举例来说,我希望此包装器除了将调用转发给内部对象之外,还能够计算每个方法被调用的次数。

EDIT2:具体来说,我正在尝试编写一个通用包装器来实现ActiveObject模式。我最终做了一个'Active'基类,该基类处理公共位(管理内部线程,排队函数调用)并为每种内部类型编写子类(模拟其接口)。

EDIT3:@ id256的答案非常有趣,我想我会在某个时候回来尝试一下该方法。

坦索

您很有可能可以operator->Wrapper类模板中进行定义实际上,这可能看起来像:

template <typename T>
class Wrapper {
    T* pT;
public:
// ...
    T* operator->() { return pT; }
// all the needed stuff to manage pT
};

例如,在STL的std::auto_ptr实现中使用了这种方法-请访问http://www.cplusplus.com/reference/memory/auto_ptr/

编辑:如果您需要通过包装对象添加一些逻辑到调用,上述解决方案是不可接受的。但是,您可以尝试将某些功能特性与模板结合使用(尽管该方法相当棘手):

#include <functional>
#include <iostream>


class A {
public: 
    int inc(int x) {
        printf("A::inc %i\n", x);
        return x+1;
    }       
};      

template <typename _Function>
struct function_logged : public _Function {
    const char* log_msg;

    function_logged(_Function fun, const char* _log_msg)
    : _Function(fun), log_msg(_log_msg) { } 
};  

template <typename T, typename U, typename V, T (U::*mf)(V)>
function_logged<std::binder2nd<std::mem_fun1_t<T,U,V> > > create_function_logged(const V& arg, const char* log_msg) {
    return function_logged<std::binder2nd<std::mem_fun1_t<T,U,V> > >(std::bind2nd(std::mem_fun(mf), arg), log_msg);
}   

template <typename T>
class Wrapper {
    T* t; // pointer, not just a plain instance, because T may not have default constructor
public:
    Wrapper(T* _t) : t(_t) { }        

    template <typename T_mem_fun_tp>
    typename T_mem_fun_tp::result_type operator()(const T_mem_fun_tp& t_mf) {
        // Handle function object as you wish, for example print logging message
        std::cout << t_mf.log_msg << '\n';
        return t_mf(t);
    }   

    ~Wrapper() { delete t; }
};  

int main() {
    Wrapper<A> wA(new A());
    int y = wA(create_function_logged<int,A,int,&A::inc>(123, "calling A::inc from Wrapper"));
    std::cout << "wA.f(123)=" << y << '\n';
    return 0;
}

输出:

calling A::inc from Wrapper
A::inc 123
wA.f(123)=124

EDIT2:此外,还可以覆盖operator->*内部Wrapper并返回某种代理对象,该代理对象包含指向实例的指针和指向方法的指针。使用这种方法,您可以控制方法执行的时间,以及预处理或后处理代理对象。可以在http://aristeia.com/Papers/DDJ_Oct_1999.pdf上找到此技术的说明。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章