2016-03-25 46 views
8

Bir hiyerarşinin tüm sınıflarının g şablon üye işlevini uyguladığını varsayalım. Hala yinelenen kod kurtulmak ve nasıl f1 ve f2 uygulamalarında yanaYinelenen kod olmadan polimorfik işlev çağrısı

struct A { 
    virtual void f1() { 
     g(5); 
    } 
    virtual void f2() { 
     g(5.5); 
    } 
private: 
    template <typename T> void g(T) {std::cout << "In A" << std::endl;} 
}; 

struct B: A { 
    // Can I get rid of this duplicate code? 
    virtual void f1() { 
     g(5); 
    } 
    virtual void f2() { 
     g(5.5); 
    } 
private: 
    template <typename T> void g(T) {std::cout << "In B" << std::endl;} 
}; 

struct C: A { 
    // Can I get rid of this duplicate code? 
    virtual void f1() { 
     g(5); 
    } 
    virtual void f2() { 
     g(5.5); 
    } 
private: 
    template <typename T> void g(T) {std::cout << "In C" << std::endl;} 
}; 

int main() 
{ 
    B b; 
    A &a = b; 
    a.f1(); 
    return 0; 
} 

tüm sınıflarda aynıdır: Bütün sınıflar bu şablonu diyoruz iki diğer fonksiyonlar f1 ve f2 aynı uygulanmasını paylaşan main'da polimorfik çağrının beklendiği gibi çalışmasını sağlayın (örn. "In B" çıkışını üretin)? f1 ve f2A olarak, B ve C ait uygulamalar değildir özdeş

cevap

3

not edin. f1 s ile kısıtlayalım. Biri, ::A::g<int> adlı bir işlevi çağırır, diğeri ise ::B::g<int> adlı bir işlevi çağırır ve üçüncü öğe ise ::C::g<int> adlı bir işlevi çağırır. Bunlar aynı olandan . sınıf adını

template <class Derived> 
struct DelegateToG : public A 
{ 
    void f1() override 
    { 
    static_cast<Derived*>(this)->g(5); 
    } 

    void f2() override 
    { 
    static_cast<Derived*>(this)->g(5.5); 
    } 
}; 

class B : public DelegateToG<B> 
{ 
    friend DelegateToG<B>; 
private: 
    template <class T> void g(T) { /*...*/ } 
}; 

class C : public DelegateToG<C> 
{ 
    friend DelegateToG<C>; 
private: 
    template <class T> void g(T) { /*...*/ } 
}; 
+0

Tekrar bir şekilde bakın: hepsi çağrı 'this-> g ' nerede '* this' a'' dinamik türüdür. Neden bu yanlış görünmeli? – AlwaysLearning

+1

@UlwaysLearning Çünkü g 'sanal değildir (ve olamaz), normal derleme zamanı kuralları bunun için geçerli demektir. Derleme zamanı kurallarının C++ 'da varsayılan değer olduğunu unutmayın. Bunun için yalnızca birkaç açık istisna vardır ('virtual', dynamic_cast',' typeid'). – Angew

+0

Sağ. Ama 'f1' sanal. 'F1' içinde' this' tipi 'a''nin dinamik türüdür. Tek istediğim, uygulamanın tekrarlanmasına gerek kalmadan türetilmiş sınıfta 'f1' aynı özdeş uygulamaya sahip olmaktır ... – AlwaysLearning

1

Sadece gibi şablon işlevi kullandığı sınıf özgü şeyler, çarpanlarına olabilir (sizin örnekte):

yapabileceğinin en iyisi bir CRTP tarzı tabanı var ise :

#include <iostream> 
using namespace std; 

class A 
{ 
private: 
    virtual auto classname() const -> char const* { return "A"; } 

protected: 
    template <typename T> void g(T) {cout << "In " << classname() << endl;} 

public: 
    virtual void f1() { g(5); } 
    virtual void f2() { g(5.5); } 
}; 

class B 
    : public A 
{ 
private: 
    auto classname() const -> char const* override { return "B"; } 
}; 

class C 
    : public A 
{ 
private: 
    auto classname() const -> char const* override { return "C"; } 
}; 

auto main() 
    -> int 
{ static_cast<A&&>(B()).f1(); } 
+0

Bu sadece bir örnekti. Aslında, 'g' uygulamaları çok farklıdır. – AlwaysLearning

+0

@AlwaysLearning: Sormadığınız bir soruya cevap veremiyorum. Afedersiniz. Telepatik değil. –

+0

Tamamen haklısınız. – AlwaysLearning

İlgili konular