2011-01-31 79 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。