Generisches Programmieren

Statische Polymorphie

Nach dem bisherigen Kenntnisstand verstehen wir unter Polymorphie folgendes:

#include <iostream>
 
// Basisklasse
class Basis 
{
  public:
    virtual void foo() { std::cout << "Basis foo" << std::endl; }
};
 
void call_foo(Basis* obj)
{
   obj->foo();
}
 
 
// Ableitung von der Basis
class Bar : public Basis
{
   public:
      void foo() { std::cout << "Bar foo" << std::endl; }
};
 
// Ableitung von der Basis
class Doe : public Basis
{
   public:
      void foo() { std::cout << "Doe foo" << std::endl; }
};
 
// Testprogramm
int main(int argc, char* argv[])
{
  Bar b;
  Doe c;
 
  // Basis "verhält" sich wie "Bar"
  call_foo(&b);  // Ausgabe: Bar foo
 
  // Basis "verhält" sich wie "Doe"
  call_foo(&c); // Ausgabe Doe foo
 
  return 0;
}

Die Auswahl der aufzurufenden Funktion erfolgt durch „spätes Binden“ (late binding) [FIXME Verweis auf Kapitel Polymorphie].

Das obige Beispiel kann man auch über Templates realisieren.

#include <iostream>
// Funktionstemplate
 
template <typename type>
void call_foo(const type& curObj)
{
   curObj.foo();
}
 
class Bar
{
  public:
    void foo() { std::cout << "Bar Foo" << std::endl; }
};
 
 
class Doe
{
  public:
    void foo() { std::cout << "Doe Foo" << std::endl; }
};
 
int main(int argc, char* argv[])
{
  Bar b;
  Doe d;
 
  // rufe konkrete Template-Funktion mit richtigem Typ auf
  call_foo(b); // Ausgabe: Bar Foo
  call_foo(d); // Ausgabe: Doe Foo
 
  return 0;
}

Was passiert hier? Wir definieren zunächst ein Funktionstemplate mit dem Namen call_foo.

template <typename type>
void foo(const type& curObj)
{
  // ....
}

Dieses ist für den Compiler eine Vorlage zum generieren der Funktion. Trifft der Compiler beim übersetzen des Programms auf einen Aufruf, zu einer Funktion mit dem konkreten Typ. Für folgendes Codestück

Bar b;
call_foo(b);

kann man sich also vorstellen, dass der Compiler eine Funktion

void call_foo(const Bar& curObj);

erzeugt. Die Abhängigkeit wir also zur Kompilierzeit aufgelöst.

Wenn der Compiler eine template Funktion sieht, wird er versuchen sie zu inlinen, sprich anstatt des Funktionsaufruf wird er den in der template Funktion verwendeten Code an der Aufrufstelle einsetzen und übersetzen.

Diskussion