2012-05-13 79 views
2

我意识到虚拟模板函数在C++中是不允许的。由于我的具体应用领域,我们处理一系列算法(通过多态和继承自然实现),并且需要强制执行一个通用接口。特定的算法类在迭代器上工作(不奇怪),但是我们想通过这些模板化函数虚拟化虚拟化。这里是我们使用boost :: mpl创建的一个解决方案的例子。我意识到这很漫长,但这是一个最小的代码示例,我可以创建它来模拟我的目标。我的具体问题在代码之后。伪造虚拟模板函数C++

#include <iostream> 
#include <vector> 
#include <boost/mpl/list.hpp> 
#include <boost/mpl/for_each.hpp> 

using namespace std; 

class A; 
class B; 
class C; 

typedef boost::mpl::list<B, C> DerivedClassList; 

template<typename Base, typename Iterator> 
struct VirtualFunc{ 
    public: 
    VirtualFunc(Base* _memory, Iterator _begin, Iterator _end) : 
     m_memory(_memory), m_begin(_begin), m_end(_end){} 

    template<typename T> 
     void operator()(T& _t) { 
     T* tptr = dynamic_cast<T*>(m_memory); 
     if(tptr != NULL){ 
      tptr->Print(m_begin, m_end); 
     } 
     } 

    private: 
    Base* m_memory; 
    Iterator m_begin, m_end; 
}; 

class A{ 
    public: 
    A(){} 
    virtual ~A(){} 

    template<typename Iterator> 
     void Print(Iterator _begin, Iterator _end){ 
     boost::mpl::for_each<DerivedClassList>(VirtualFunc<A, Iterator>(this, _begin, _end)); 
     } 
}; 

class B : public A { 
    public: 
    B(){} 
    virtual ~B(){} 

    template<typename Iterator> 
     void Print(Iterator _begin, Iterator _end){ 
     cout << "Begin::" << *_begin << endl; 
     } 
}; 

class C : public A { 
    public: 
    C(){} 
    virtual ~C(){} 

    template<typename Iterator> 
     void Print(Iterator _begin, Iterator _end){ 
     for(Iterator it = _begin; it!=_end; it++) 
      cout << "Iterator::" << *it << endl; 
     } 
}; 

int main(){ 
    vector<size_t> numbers; 
    for(size_t i = 0; i<5; i++) 
    numbers.push_back(i); 

    A* printBegin = new B(); 
    A* printAll = new C(); 
    //faking virtualism will print just begin 
    printBegin->Print(numbers.begin(), numbers.end()); 
    //faking virtualism will print all 
    printAll->Print(numbers.begin(), numbers.end()); 
} 

那么这个“假虚拟”模板函数的缺陷是什么?有没有更简洁的方法来做到这一点?

同样原谅代码标准,他们是我们在我的工作场所使用的。

+0

这可以是更适合于[代码审查](http://codereview.stackexchange.com/)。 –

+0

谢谢,我现在在这里发布。 – pippin1289

回答

0

为什么不用经典的双重调度模式来取代。看起来你知道你的类层次结构在基本级别 - 所以我会使用以下内容。众所周知,Visitor或DoubleDispatch模式,并消除无效的dy​​namic_cast。坦率地说 - 如果我看到的dynamic_cast <>我总是想着双重分发,

已知clasees:

class A; 
class B; 
class C; 

虚拟主义的起点:

class IVirtualFunc { 
    public: 
    virtual void callFor(B& memory) = 0; 
    virtual void callFor(C& memory) = 0; 
}; 

执行情况的模板参数:

template<typename Iterator> 
class VirtualFunc : public IVirtualFunc { 
    public: 
    VirtualFunc (Iterator _begin, Iterator _end) : begin(_begin), end(_end) {} 
    virtual void callFor(B& memory); 
    virtual void callFor(C& memory); 
    private: 
    Iterator begin; 
    Iterator end; 
}; 

实际的i的抽象基类mplementations:

class A{ 
    public: 
    template<typename Iterator> 
    void Print(Iterator _begin, Iterator _end) { 
     VirtualFunc<Iterator> vFunc(_begin, _end); 
     dispatch(vFunc); 
    } 
    virtual void dispatch(IVirtualFunc&) = 0; 
}; 

一是实际执行与双击它讯(VirtualFunc<Iterator>::callFor(B& b)):

class B : public A { 
    public: 
    B(){} 
    virtual ~B(){} 

    template<typename Iterator> 
     void Print(Iterator _begin, Iterator _end){ 
     cout << "Begin::" << *_begin << endl; 
     } 
    virtual void dispatch(IVirtualFunc& vf) { vf.callFor(*this); } 
}; 

template<typename Iterator> 
void VirtualFunc<Iterator>::callFor(B& b) 
{ 
    b.Print(begin, end); 
} 

二实际执行双调度它(VirtualFunc<Iterator>::callFor(C& c)):

class C : public A { 
    public: 
    C(){} 
    virtual ~C(){} 

    template<typename Iterator> 
     void Print(Iterator _begin, Iterator _end){ 
     for(Iterator it = _begin; it!=_end; it++) 
      cout << "Iterator::" << *it << endl; 
     } 
    virtual void dispatch(IVirtualFunc& vf) { vf.callFor(*this); } 
}; 
template<typename Iterator> 
void VirtualFunc<Iterator>::callFor(C& c) 
{ 
    c.Print(begin, end); 
} 

和论证它的工作原理:

int main(){ 
    vector<size_t> numbers; 
    for(size_t i = 0; i<5; i++) 
    numbers.push_back(i); 

    A* printBegin = new B(); 
    A* printAll = new C(); 
    //faking virtualism will print just begin 
    printBegin->Print(numbers.begin(), numbers.end()); 
    //faking virtualism will print all 
    printAll->Print(numbers.begin(), numbers.end()); 
} 

OUTPUT:

Begin::0 
Iterator::0 
Iterator::1 
Iterator::2 
Iterator::3 
Iterator::4