2013-10-19 101 views
2

我有一个主机类,它需要两个策略,sayhellotalk。策略talk是一个类模板,它本身需要例如sayhello。 问题是sayhello::saySomething含糊不清host2(我试图用virtual来解决这个钻石问题)。基于策略的设计中的模糊继承

我该如何解决这个歧义?或者总体来说对这些问题有更好的设计?

例子:

#include <iostream> 

class sayhello { 
protected: 
    void saySomething(void) { 
     std::cout<<"Hello!"<<std::endl; 
    } 
}; 

template<typename T> 
class talk : private T { 
protected: 
    void doSomething(void) { 
     T::saySomething(); 
    } 
}; 

template<typename T> 
class host1 : virtual T { 
public: 
    void hostAction(void) { 
     T::doSomething(); 
    } 
}; 

template<typename T, typename L> 
class host2 : private T, private L { 
public: 
    void hostAction(void) { 
     T::doSomething(); 
     L::saySomething(); 
    } 
}; 

int main() { 
    host1<talk<sayhello> > HOST1; 
    HOST1.hostAction(); // ok that works 

    host2<talk<sayhello>,sayhello> HOST2; 
    HOST2.hostAction(); // error, ambiguity! 

    return 0; 
} 

回答

2

您可能会滥用继承权,但只需添加几个virtual个关键字在这两个talkhost2

#include <iostream> 

class sayhello { 
protected: 
    void saySomething(void) { 
     std::cout<<"Hello!"<<std::endl; 
    } 
}; 

template<typename T> 
class talk : virtual T { 
protected: 
    void doSomething(void) { 
     T::saySomething(); 
    } 
}; 

template<typename T> 
class host1 : virtual T { 
public: 
    void hostAction(void) { 
     T::doSomething(); 
    } 
}; 

template<typename T, typename L> 
class host2 : virtual T, virtual L { 
public: 
    void hostAction(void) { 
     T::doSomething(); 
     L::saySomething(); 
    } 
}; 

int main() { 
    host1<talk<sayhello> > HOST1; 
    HOST1.hostAction(); // ok that works 

    host2<talk<sayhello>,sayhello> HOST2; 
    HOST2.hostAction(); // error, ambiguity! 

    return 0; 
} 

Live Example

+0

谢谢,TemplateRex,恰好解决了这个问题。你能否解释一下为什么你有这样的感觉,遗传被滥用了? –

+0

@the_ducky因为一个好的基于策略的设计具有*正交*策略,不可能通过不同的策略繁殖继承相同的类。一种避免这种情况的方法就像@DanielFrey所说的那样,使用虚拟类。但在你的情况下,你可能会想'sayHello :: saySomething'和'talk :: doSomething'是否可以成为'static'成员函数,所以你不必从'T'继承[[example]( http://coliru.stacked-crooked.com/a/b3921d80aba9b14a)) – TemplateRex

1

你可以添加一个虚拟类:

template<typename T> struct dummy : T {}; 

template<typename T, typename L> 
class host2 : private T, private dummy<L> { 
public: 
    void hostAction(void) { 
     T::doSomething(); 
     dummy<L>::saySomething(); 
    } 
}; 

在某些情况下,你可能会需要直接转换为L,它应该像这样工作:

L& getL() 
{ 
    return static_cast<L&>(static_cast<dummy<L>&>(*this)); 
}