2016-02-18 11 views
6

W jaki sposób wypełnisz metodę, jeśli klasa podstawowa jej nie dostarcza. Chciałbym ponownie użyć metody klasy bazowej, jeśli jest ona dostarczona.Dopasowywanie dostarczonej przez szablon klasy podstawowej

Np

#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

dobrze, jeśli naprawdę chcesz zrobić to w ten sposób, masz problem z zaproszenia porządek mimo wszystko. Pochodna jest typem i tak długo jak Derived ma funkcję 'm()', zawsze będzie nadpisywać funkcję podstawową 'm()' –

+0

Łączymy pojęcia: dziedziczenie, funkcje wirtualne i szablony. W sumie jest to zapach kodu. Mając szablony, unikaj dziedziczenia i funkcji wirtualnych. –

Odpowiedz

8

Z SFINAE, można zrobić

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

Aby być w ogóle, należy zdefiniować funkcję w każdym razie pod inną Podpis:

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

Następnie można użyć metod podanych w this thread w celu sprawdzenia niezależnie od tego, czy klasa podstawowa ma funkcję : Wreszcie, można użyć jej jako

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

Jak Aslay Berby już powiedział to prawdopodobnie nie jest to sposób, który chciałbyś iść. Jeśli chcesz zaimplementować coś podobnego do cech lub projektu opartego na regułach, poniższy kod może być tym, czego szukasz. W rzeczywistości takie projekty są używane dość powszechnie i mają również wartość idiomatyczną.

#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 

Zobacz także: https://en.wikipedia.org/wiki/Policy-based_design

Powiązane problemy