2016-02-18 100 views
6

如果基類不提供它,你將如何去填充方法。如果提供的話,我想重用基類方法。修改模板提供的基類

如:

#include <iostream> 
struct Base0 { }; 
struct Base1 { void m() { std::cout<<"Base1\n"; } }; 

template<typename T> 
struct Derived : public T { 
    //if T doesn't provide m, define it here, otherwise reuse the base class method 
    void m(){ /*? std::cout<<"Derived\n"; ?*/ } 
}; 

int main(){ 
    Derived<Base0> d0; 
    d0.m(); //should print "Derived" 
    Derived<Base1> d1; 
    d1.m(); //should print "Base1" 
} 
+0

好吧,如果你真的很喜歡做這種方式,你得到了與調用問題無論如何,順序。 Derived是類型,只要Derived有一個函數'm()'它總是會覆蓋基函數'm()' –

+0

您正在混合的概念:繼承,虛函數和模板。總之它是一種代碼味道。有模板,避免繼承和虛擬功能。 –

回答

8

隨着SFINAE,你可以做

template<typename T> 
struct Derived : public T { 
private: 
    template <typename U = T> 
    auto m_impl(int) -> decltype(std::declval<U&>().m()){ this->U::m(); } 

    template <typename U = T> 
    void m_impl(...) { std::cout<<"Derived\n"; } 

public: 
    void m() { m_impl(0); } 
}; 

Demo

2

爲了一般情況下,您都應該定義在不同的簽名功能:

template<typename T> 
struct Derived : public T 
{ 
    auto m(std::false_type) { std::cout<<"Derived\n"; } 
}; 

然後你可以使用在this thread給出的方法,以便檢查基類是否具有功能m()

template <typename...> 
using void_t = void; 

template <typename T, template <typename> class D, typename = void> 
struct detect : std::false_type {}; 

template <typename T, template <typename> class D> 
struct detect<T, D, void_t<D<T>>> : std::true_type {}; 

template <typename T> 
using has_m = decltype(std::declval<T>().m()); 

最後,你可以使用它作爲

template<typename T> 
struct Derived : public T 
{ 
    auto m(std::true_type) { return T::m(); } 
    auto m(std::false_type) { std::cout<<"Derived\n"; } 
    auto m() { return m(detect</* const */ T, has_m>{}); } 
           ^^^^^^^^^^ 
           //if m() is const 
}; 

0

由於Aslay Berby已經表示,這可能不是你想的路要走。如果你想實現像特質或基於策略的設計,下面的代碼可能是你正在尋找的。事實上,這種設計使用相當普遍,也具有慣用價值。

#include <iostream> 
using namespace std; 

struct StandardTraits {void foo() {cout << "standard" << endl;}}; 

struct Traits1 {void foo() {cout << "traits1" << endl;}}; 
struct Traits2 {void foo() {cout << "traits2"<< endl;}}; 

template<typename T = StandardTraits> 
class SomeClass 
{ 
public: 
    typedef T Traits; 

    void useTraits() {traits.foo();} 

private: 
    Traits traits; 
}; 

int main() { 

    SomeClass<> x; 
    SomeClass<Traits1> y; 
    SomeClass<Traits2> z; 

    x.useTraits(); 
    y.useTraits(); 
    z.useTraits(); 

    return 0; 
} 

// output: 
// standard 
// traits1 
// traits2 

參見:https://en.wikipedia.org/wiki/Policy-based_design