Praxisorientierte Einführung in C++ (Variadische Funktionen) Christoph Elbrechter, Florian Paul Schmidt Universität Bielefeld April 12, 2012 Christoph Elbrechter, Florian Paul Schmidt Praxisorientierte Einführung in C++ (onen) April 12, 2012 1 / 15
überblick onen Motivation Syntax Beispiel printf-light Diskussion Alternativen Christoph Elbrechter, Florian Paul Schmidt Praxisorientierte Einführung in C++ (onen) April 12, 2012 2 / 15
Funktionen abstrahierten bislang über... Werte void draw_cicle ( int cx, int cx, int radius ); Typen template < class T> void show ( const T & t); Christoph Elbrechter, Florian Paul Schmidt Praxisorientierte Einführung in C++ (onen) April 12, 2012 3 / 15
Bisher noch nicht möglich: Abstraktion über die Anzahl von Parametern Das ist natürlich durch überladung möglich Oder Default-Parameter Christoph Elbrechter, Florian Paul Schmidt Praxisorientierte Einführung in C++ (onen) April 12, 2012 4 / 15
Überladung (nicht so schön!) überladung 1 int * create_tuple ( int a) { 2 int * p = new int [1]; 3 p [0] = a; 4 return p; 5 } 6 7 int * create_tuple ( int a, int b){ 8 int * p = new int [2]; 9 p [0]= a; p [1]= b; 10 return p; 11 } 12 int * crate_tuple ( int a,int b, int c ){... } usw. Christoph Elbrechter, Florian Paul Schmidt Praxisorientierte Einführung in C++ (onen) April 12, 2012 5 / 15
Einen guten Ausweg bieten hier sog. variadische Funktionen Diese bieten darüber hinaus auch noch die Möglichkeit über die Typen der Parameter zu abstrahieren (aber eher krude) Christoph Elbrechter, Florian Paul Schmidt Praxisorientierte Einführung in C++ (onen) April 12, 2012 6 / 15
Syntax RueckgabeTyp bezeichner ( ParameterListe,...) Man beachte die Punkte, sie sind Teil der Syntax in diesem Fall ParameterListe darf hier nicht leer sein, muss also mindestens ein Typ Bezeichner -Paar enthalten Beispiel: void printf ( const char *fmt,...); Christoph Elbrechter, Florian Paul Schmidt Praxisorientierte Einführung in C++ (onen) April 12, 2012 7 / 15
Implementation an einem Beispiel on 1 int * create_tuple ( int n,...){ 2 va_list l; 3 va_start (l, n); 4 int *p = new int [n]; 5 for ( int i =0;i<n ;++ i){ 6 p[i] = va_arg (l,int ); 7 } 8 va_end (l); 9 return p; 10 } 11 12 int main (){ 13 int * t1 = create_tuple (5,1,2,3,4,5); 14 int * t2 = create_tuple (2,10,20); 15 } Christoph Elbrechter, Florian Paul Schmidt Praxisorientierte Einführung in C++ (onen) April 12, 2012 8 / 15
Implementation für unterschiedliche Parametertypen Problem: Innerhalb der Implementation kann nicht ermittelt werden um welchen Typ es sich tatsächlich handelt Ausweg durch Format-String Hier demonstriert an einer light-version von printf Christoph Elbrechter, Florian Paul Schmidt Praxisorientierte Einführung in C++ (onen) April 12, 2012 9 / 15
printf() - Light 1 using namespace std ; 2 void printf_light ( const char *fmt,...){ 3 va_list l; 4 va_start (l, fmt ); 5 while (* fmt ){ 6 switch (* fmt ){ 7 case i : cout << va_arg (l, int ); break ; 8 case d : cout << va_arg (l, double ); break ; 9 case l : cout << va_arg (l, long ); break ; 10 case u : cout << va_arg (l, unsigned int ); break ; 11 case x : cout << va_arg (l, unsigned long ); break ; 12 case p : cout << va_arg (l, void *); break ; 13 default : 14 cerr << " unknown format char!" << endl ; 15 va_end ( l); return ; 16 } 17 fmt ++; cout <<, ; 18 } 19 cout << std :: endl ; va_end ( l); 20 } Christoph Elbrechter, Florian Paul Schmidt Praxisorientierte Einführung in C++ (onen) April 12, 2012 10 / 15
Verwendung... Benutzung von printf() - Light 21 int main (){ 22 printf_light (" iid ",42,666,4.3); 23 24 vector <int > * v = new vector <int >(7); 25 printf_light ("up",v-> size (),v); 26 } Ausgabe: 42,666,4.3, 7,0 x804b008, Christoph Elbrechter, Florian Paul Schmidt Praxisorientierte Einführung in C++ (onen) April 12, 2012 11 / 15
Grösstes Problem: onen unterstützen nur POD-Typen (und davon nicht mal alle richtig) Unterstützte Typen: int,uint,long,ulong,double,void* Theoretisch können ja Pointer auf beliebige Typen über das void* Interface geschleust werden Allerdings: Fehlerträchtig + Umständlich Christoph Elbrechter, Florian Paul Schmidt Praxisorientierte Einführung in C++ (onen) April 12, 2012 12 / 15
Weitere Nachteile: Laufzeit-parsen von eigentlich festen Typen relativ ineffizient Programmabsturz falls nicht POD-Referenz/Objekt übergeben wird Aber das richtige printf und die verwandte Funktion sprintf ist relativ mächtig und kompakt, wenn formatierte Ausgaben erstellt werden sollen Christoph Elbrechter, Florian Paul Schmidt Praxisorientierte Einführung in C++ (onen) April 12, 2012 13 / 15
Alternativen: Daten in einen Container packen void show ( std :: vector <int > data ); Templates Template 27 template < class A, class B, class C, class D, class E> 28 void show ( const A &a, const B& b usw..){ 29 std :: cout << a <<, << b <<, << usw.. 30 } (Im C++-1x-Standard wird es dann auch variadische Template geben) Christoph Elbrechter, Florian Paul Schmidt Praxisorientierte Einführung in C++ (onen) April 12, 2012 14 / 15
Alternativen: überladen von Operatoren std :: cout << 3 << 4.5 << " hallo " << std :: endl Aber das ist nur syntaktischer Zucker für konsekutive Funktionsaufrufe Arbiträre Datentypen QVariant, boost::any Eigentlich sind variadische Funktionen nicht soooo beliebt bei C++-Programmierern Christoph Elbrechter, Florian Paul Schmidt Praxisorientierte Einführung in C++ (onen) April 12, 2012 15 / 15