2014-08-28 16 views
11
#include <iostream> 

template<typename Impl> 
struct renderer{ 
    void get(){ 
     static_cast<Impl*>(this)->get(); 
    } 
}; 
struct open_gl : public renderer<open_gl>{ 
    void get(){ 
     std::cout << "OpenGL" << std::endl; 
    } 
}; 
struct direct_draw : public renderer<direct_draw>{ 
    void get(){ 
     std::cout << "DX" << std::endl; 
    } 
}; 
template<typename T> 
void print_renderer(renderer<T> r){ 
    r.get(); 
} 
int main() { 
    auto gl = open_gl(); 
    auto dx = direct_draw(); 
    print_renderer(gl); 
    print_renderer(dx); 
} 
  1. Dlaczego nie mogę zmienić parametr print_renderer do void print_renderer(const renderer<T> &r)? cannot convert 'this' pointer from 'const renderer<open_gl>' to 'renderer<open_gl> &' `Static polimorfizm w C++

  2. Dlaczego otrzymuję błąd wykonania kiedy zmień metodę get w open_gl z dostać do get1? Czy nie powinno to powodować błędu kompilatora? Error = Stack overflow

** Uwaga Używam najnowszy MSVC

+1

I ... mix-n-meczu! http://coliru.stacked-crooked.com/a/25722fa147efbbd3 –

Odpowiedz

12

1) Ponieważ get nie jest funkcją const członkiem: to nie może sprawić, że obietnicy nie modyfikować (const) argument.

Można zadeklarować get jako const i kompiluje grzywny:

void get() const { ... } 

2) Metoda baza get zostanie wywołana, wchodząc nieskończonej rekurencji: przepełnienie stosu.

Jeśli zadeklarujesz czynność override (to musi być wirtualny), kompilator wygeneruje błąd, jeśli nie faktycznie zastąpić metodę Base:

void get1() override { ... } // Compiler error 
void get() override { ... } // Ok 

Uwaga:

Tytuł brzmi "Statyczny polimorfizm w C++", ale myślę, że źle zrozumiałeś, co jest statycznym polimorfizmem: nie musi (musi) korzystać z dziedziczenia (tak jak ty). Zamiast tego, szablony pisane kodem kompilacyjnym będą statycznie "rozwiązywać" wywołania funkcji.

Oznacza to, że nie trzeba związanych rodzajów, nie trzeba klasy bazowej renderer w ogóle, a można po prostu wykonaj następujące czynności (w tym przypadku, zmiana nazwy na get1będzie powodować błąd kompilatora) :

#include <iostream> 

struct open_gl { 
    void get(){ 
     std::cout << "OpenGL" << std::endl; 
    } 
}; 
struct direct_draw { 
    void get(){ 
     std::cout << "DX" << std::endl; 
    } 
}; 

template<typename T> 
void print_renderer(T r){ 
    r.get(); 
} 

int main() { 
    auto gl = open_gl(); 
    auto dx = direct_draw(); 
    print_renderer(gl); 
    print_renderer(dx); 
} 

Live demo

+0

Dzięki, o moje drugie pytanie. Czy można rzucić błąd kompilatora, gdy 'get' nie jest zaimplementowany? Coś jak przesłonięcie? –

+0

@MaikKlein tak zobacz moją edycję – quantdev

+0

Jak mogę uczynić 'void get()' wirtualnym, jeśli chcę statycznego polimorfizmu? –

5
  1. becuase get nie zaznaczono const.
  2. Ponieważ używana jest metoda klasy bazowej (niezwiązana z rzutowaniem) i przechodzi w nieskończoną pętlę.