PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : C++ Ein-Zeilen-Funktionen in Header schreiben? Warum eigentlich?



axeljaeger
05-05-2004, 11:45
Ich hab mich daran gewöhnt, einzeilige Methoden in C++ direkt in die Deklaration der Klasse zu schreiben. Get- und Set-Methoden sind da die Kandidaten. Das führt wohl dazu, dass diese Methoden automatisch Inline werden. Jetzt hab ich aber ein vernünftiges Argument gegen diese Praxis gehört:

"Wenn man eine Methode in den Header schreibt, so kann sie nachdem eine Library kompiliert wurde, noch verändert werden. Das muss nicht unbedingt auffallen, kann aber dazu führen, dass sich eine Library nicht mehr so verhält, wie in der Dokumentation beschrieben. Der Compiler kann ja trotzdem Inline-Optimierungen vornehmen."

Ich halte dieses Argument für so gut, dass ich fast schon dazu übergegangen bin, jede kleine Klickermethode in die Implementation (Cpp) zu schreiben, einfach weil ich auch noch kein vernünftiges Argument dagegen gehört hab. Jetzt brauche ich da mal Meinungen....

anda_skoa
05-05-2004, 16:37
Komisches Argument.
Wenn man den Quellcode von etwas ändert, will man wahrscheinlich, dass es sich anders verhält.

Wenn jemand den Header ändert, vorrausgesetzt die Lizenz erlaubt das, will er wahrscheinlich dieses neue Verhalten.

Ciao,
_

nobody0
05-05-2004, 16:42
Das geht alles; Du kannst ja auch .c und .cpp-Dateien inkludieren und auch header-Dateien in header-Dateien inkludieren.
Die erste Variate kann man nehmen um z. B. die alleraktuellste Version zu verwenden (die man z. B. vor einer Minute erstellt hat) und die letzte ist z. B. eine Unsitte, die in den Kernel-Sourcen verbreitet ist (weil damit etw. Tipparbeit gespart wird).

Am Schlimmsten ist aber die Unsitte Assembler-Makros in Header-Dateien zu packen, denn wenn ein Prettyprinter wie indent diese Datein bearbeitet hat, bekommt man die merkwürdigsten Fehlermeldungen, weil der Assemblere nicht mehr das versteht, was indent nach dem C-Standard eigentlich korrekt gemacht hat.

Dass eine Methode, die man in den Header schreibt, noch nach der Library verändern, stimmt nicht; die ist ja fest eincompiliert.
Im Worst case kann jemand böswillig die Header-Datei ändern und z. B. eine Variable namens class anlegen oder einige Typen ändern, aber das ändert ja die Lib nicht.
Weil aber ein user aber normalerweise keine Schreibrechte dafür hat, gehört zu sowas schon "kriminelle Energie" oder zumindest viel Dämlichkeit.

wraith
05-05-2004, 17:18
DAS Hauptargument gegen geinlined Methoden ist doch, das man damit die Kopplung von Programmteilen untereinander erhöht (und das ist immer schlecht)
Eine Methode im Header implementiert zieht bei Veränderungen die Kompilierung von allen Dateien nachsich, die diesen Header includen.
Ein Header für eine C++ Klasse sollte (im Idealfall) nur das Interface darstellen, und die Implementierung austauschbar sein, _ohne_ das andere Programmteile davon betroffen sind (im Sinne einer Neukompilierung).
Private Member (und auch Methoden) kann man noch (mit etwas Mehraufwand) komplett aus dem Header entfernen, und kann damit sogar die interne Implementierung (nehme ich jetzt std::vector oder std::deque?) ändern, ohne Neukompilierung abhängiger Programmteile.


Original geschrieben von anda_skoa
Komisches Argument.
Ja, verstanden hab' ich das auch nicht.


Original geschrieben von nobody0
Das geht alles; Du kannst ja auch .c und .cpp-Dateien inkludieren und auch header-Dateien in header-Dateien inkludieren.
Die erste Variate kann man nehmen um z. B. die alleraktuellste Version zu verwenden (die man z. B. vor einer Minute erstellt hat) und die letzte ist z. B. eine Unsitte, die in den Kernel-Sourcen verbreitet ist (weil damit etw. Tipparbeit gespart wird).
Bist du ein Anhänger der Philosophie von Rob Pike, oder warum ist es auf einmal eine Unsitte in Headern Header zu includieren?

axeljaeger
05-05-2004, 18:27
Mich überzeugt das Argument mit dem Verändern schon. Aber was spricht denn dagegen, alles in die cpp zu machen?

nobody0
05-05-2004, 18:54
Original geschrieben von wraith

Bist du ein Anhänger der Philosophie von Rob Pike, oder warum ist es auf einmal eine Unsitte in Headern Header zu includieren?

Das ist auch in den C-FAQs erläutert.

Ich verwende das generell nicht, so wie z. B. goto, also ganz ganz selten doch (so wie z. B. longjmp), wenn es ohne viel aufwändiger wäre.
Der Grund es ganz einfach, dass durch Includieren das wichtige Prinzip der Orthogonalität massiv verletzt wird. Das merkt man z. B. wenn man ein Kernel-Modul kompilieren will und die nötigen Header-File zusammensuchen muß (z. B. weil der Target-Kernel ganz andere Sourcen hat); da hat man ohne sowas wie Tags kaum eine Change und es kommt sogar auf die Reihenfolge der includes an! :eek: Das ist einfach sehr schlechter Stil!
Umgekehrt ist es noch schwerer; man bekommt kaum heraus wo eine Header-Datei überall includiert wird; allein nach dem direkten include zu suchen reicht da nicht.

Es gibt auch andere Folgen wie z. B. dass eine fehlende Header-Datei unnötige Folgefehler dadruch produziert, dass die indirekt includierten headers fehlen.

wraith
05-05-2004, 19:50
Original geschrieben von nobody0
Das ist auch in den C-FAQs erläutert.
In 'meinen' C-FAQs wird nicht viel dazu erläutert
http://www.eskimo.com/~scs/C-faq/q10.7.html

Da das Thema auch erst vor kurzen in comp.lang.c aufkam, ein Kommentar daraus (bezog sich auf die Include Regel von Rob Pike)

Original geschrieben von Dan Pop
It's a nightmare for both the implementor and the user.

Damn right.


Ich verwende das generell nicht,

Dann kann ich nur hoffen, daß ich nie einen größeren Code von dir maintainen muß ;).
Wenn du dann noch *.cpp/*.c Dateien includest geb' ich ganz auf ;).


Original geschrieben von axeljaeger
Aber was spricht denn dagegen, alles in die cpp zu machen?

Erstmal garnichts.
Wenn es keine zwingende Notwendigkeit gibt (zb. templates), die Methode im Header zu implementieren, dann tue es auch nicht.
Wenn du später (mittels Profiler oder ähnlichem) rausbekommen hast, daß deine Methode geinlined Vorteile für Programmgröße oder Laufzeit bringt, dann kannst du darüber nachdenken sie im Header zu implementieren.

nobody0
06-05-2004, 11:40
Original geschrieben von wraith
Dann kann ich nur hoffen, daß ich nie einen größeren Code von dir maintainen muß ;).
Wenn du dann noch *.cpp/*.c Dateien includest geb' ich ganz auf ;).


Weil die Unsitte Code wie C- oder Assembler-Funktionen in Header-Dateien zu packen weit verbreitet ist, nehmen es viele nicht genau; für viele gibt's keinen Unterschied zwischen *.c/*.cpp - und *.h - Dateien. Für die ist es auch normal beide Sorten zu includieren.

axeljaeger
06-05-2004, 15:41
Original geschrieben von wraith

Erstmal garnichts.
Wenn es keine zwingende Notwendigkeit gibt (zb. templates), die Methode im Header zu implementieren, dann tue es auch nicht.
Wenn du später (mittels Profiler oder ähnlichem) rausbekommen hast, daß deine Methode geinlined Vorteile für Programmgröße oder Laufzeit bringt, dann kannst du darüber nachdenken sie im Header zu implementieren.

Wenn ich die Implementation nicht in den Header packe, kann sie der Compiler doch trotzdem inline machen, oder irre ich? Es gibt doch sogar einen switch, mit dem der g++ bevorzugt Funktionen inlinen soll.

wraith
06-05-2004, 15:48
Original geschrieben von axeljaeger
Wenn ich die Implementation nicht in den Header packe, kann sie der Compiler doch trotzdem inline machen, oder irre ich?
Hier ist ein Artikel zu den verschiedenen Stufen des inlines.
Der Punkt "Answer C: At Link Time" ist für dich interessant.



Es gibt doch sogar einen switch, mit dem der g++ bevorzugt Funktionen inlinen soll.
Benenne den mal.

axeljaeger
07-05-2004, 18:38
Original geschrieben von wraith

Benenne den mal.
-finline-functions

ab -O3 serienmäßig beim compile drinn.

wraith
07-05-2004, 18:57
Original geschrieben von axeljaeger
-finline-functions

ab -O3 serienmäßig beim compile drinn.
Ja, die Erklärung dazu ist nicht so aufschlußreich, ob hier nur die Funktionen gemeint sind, die der Compiler 'sehen' kann.
Ich nehme es aber stark an, sonst hätte sie es explizit dazu geschrieben.
Also gehe davon aus, daß inlining nicht über Übersetzungseinheiten hinweg funktioniert, und nur in Headern definierte Funktionen funktionieren.


-finline-functions
Integrate all simple functions into their callers. The compiler heuristically decides which functions are simple enough to be worth integrating in this way.

If all calls to a given function are integrated, and the function is declared static, then the function is normally not output as assembler code in its own right.

axeljaeger
07-05-2004, 19:05
Du hast da ja einen Link gepostet, in dem steht was von inlinen von Methoden aus anderen object-files oder gar libs und dass das wenigstens der MS-Compiler kann.