Inline Methoden

In der klassenorientierten Programmierung kommt es häufig vor, dass eine Methode nur aus einer einzigen Anweisung besteht. Dies geschieht besonders oft bei sogenannten Gettern. Hierbei ist der Aufwand, die Funktion zu rufen aufwendiger als das, was die Funktion eigentlich leistet.

In dem Fall kann man dem Compiler empfehlen, den Funktionsaufruf wegzulassen und die wenigen Anweisungen direkt da auszuführen, wo eigentlich die Funktion gerufen werden soll.

Eine inline-Funktion wird also überall da eingesetzt, wo eigentlich die Funktion gerufen werden sollte.

Schauen wir uns die Klasse file an:

class File
{
private:
  FILE       * Handle;
  char const * Filename;
  unsigned int Size;
 
public:
  File( char const * filename );
  ~File();
 
  bool Read( char * buffer, int size );
  bool Write( char * buffer, int size );
 
  unsigned int GetSize();
 
  bool Close();
};

Im Quelltext findet sich die Implementierung von GetSize():

unsigned int File::GetSize()
{
  if( !Handle )
    return -1;
 
  return Size;
}

Die Funktion ist sehr klein und wird die Funktion häufig gerufen, so ist der Funktionsaufruf das, was die meiste Rechenzeit benötigt. Also versuchen wir den Funktionsaufruf zu unterdrücken.

Jeder, der die Funktion rufen kann, muss die Klasse File kennen, also die Datei file.h inkludieren. Die Implementierungsdatei (also die .cpp-Datei) wird dabei aber nicht gelesen. Aus diesem Grund darf die Funktion auch nicht mehr wirklich implementiert werden und muss aus dem Quelltext verschwinden.

Stattdessen muss in der Header-Datei beschrieben sein, was passieren muss, wenn jemand GetSize() ruft. Wir entfernen also die Implementation aus der cpp-Datei und fügen sie mit dem Schlüsselwort inline in die Headerdatei ein:

#include <stdio.h>
 
class File
{
private:
  FILE       * Handle;
  char const * Filename;
  unsigned int Size;
 
public:
  File( char const * filename );
  ~File();
 
  bool Read( char * buffer, int size );
  bool Write( char * buffer, int size );
 
  inline unsigned int GetSize()
  {
    if( !Handle )
      return -1;
 
    return Size;
  }
 
  bool Close();
};

Das war's. Der Funktionsaufruf findet nun nicht mehr statt, obwohl sich das Hauptprogramm nicht ändert:

int main( void )
{
  File myFile( "example.txt" );
 
  printf( "Datei ist %d Bytes groß\n", myFile.GetSize() );
 
  return EXIT_SUCCESS;
}

Statt myFile.GetSize() wird nun

if( !myFile.Handle )
  return NULL;
 
return myFile.Size;

eingefügt. Hierbei bedeutet return, dass der Wert direkt in die Parameterliste kopiert wird, weil die Inlinefunktion ihre Rückgabe ja ebenfalls direkt in die Parameterliste kopiert hätte.

Inlinefunktionen lohnen sich besonders für sehr kleine Funktionen. Inlinefunktionen sind aber nicht möglich, sobald Rekursion ins Spiel kommt: Ruft sich eine Funktion selbst, so kann eine Funktion nicht in sich selbst eingesetzt werden.

Die Änderungen lassen sich als vollständiges Projekt hier herunterladen.