2013-10-19 34 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)); 
}