2011-01-31 84 views
1

不知道如何清楚地说明主题。C++/Boost模板运行时多态性

假设我有一堆函子类提供了一些方法。现在我想创建一个代理类,它将方法调用重定向到其中一个底层函子。

如:

template<class F> 
class proxy_impl : proxy { 
    F f; 
    void method() { f.method(); } 
}; 

template<> 
class proxy_impl<void> { 
    virtual void method() = 0; 
}; 

class proxy { 
    auto_ptr<proxy_impl<void> > *impl_; 
    template<class F> 
    proxy(F f) : impl_(new proxy_impl<F>(f)) {}  
    void method() { 
     impl->method(); 
    } 
}; 

这是什么模式打来电话,确实有提升执行?

没有函子直接继承的原因是因为函数可能会像无名的lambda表达式那样。

好的,所以看起来我需要像boost :: any和boost :: function之类的东西。

+0

你不需要'方法'虚拟 – KitsuneYMG 2011-01-31 01:51:45

+0

我一直困惑这一段时间,我认为你在做一件很奇怪的事情,我认为它不值得头痛的尝试去理解它,它对未来的可维护性预示着非常坏的病。 – Omnifarious 2011-01-31 03:08:42

+0

@Omnifarious同意。 – KitsuneYMG 2011-01-31 03:35:21

回答

1

它看起来像你试图重新发明基于对象的多态性......很糟糕。

here'sow做你想做什么

class interface { virtual void method()=0; } 
class impl1 : public interface { void method(); } 
class impl2 : public interface { void method(); } 

...//example usage 
interface i *; 
if (cond) i = new impl1(); else i= new impl2(); 
i->method();//calls whichever implementing method was constructed. 
0

我不认为我真的能理解。它似乎所有你想要的是能够链函子一起:

struct null_functor { void method() { }; }; 

template <typename F = null_functor> 
struct functor1 { 
    F f; 
    void method() { 
    std::cout << "functor1 called!" << std::endl; 
    f.method(); 
    }; 
}; 

template <typename F = null_functor> 
struct functor2 { 
    F f; 
    void method() { 
    std::cout << "functor2 called!" << std::endl; 
    f.method(); 
    }; 
}; 

int main() { 
    functor1 f1; 
    f1.method(); 

    functor1<functor1> f11; 
    f11.method(); 

    functor2<functor1> f21; 
    f21.method(); 

    return 0; 
}; 

如果您需要动态最重要的是结合,才使一个仿函数是一个基类与虚拟方法,并从我获得其他函子吨。你也可以使用Boost.Bind。

1

正如你所建议的,这可以用boost.any和boost.function来完成。具体做法是:

struct proxy { 
    template <typename T> 
    proxy(T t) : obj_(t) { 
    method = [&obj_] { boost::any_cast<T&>(obj_).method(); } 
    } 
    boost::function<void()> method; 
private: 
    boost::any obj_; 
}; 

如果.method()是常量,那么你就可以废除了boost ::任何,只是有拉姆达捕获由价值T对象。事实上,在这种情况下,你可以放弃代理对象,只使用一个纯粹的boost :: function。