Resource icon

[C++] Das PIMPL-Prinzip 2015-03-24

No permission to download

-AB-

Well-Known Member
c-b Team
c-b Experte
#1
-AB- hat eine neue Ressource erstellt:

[C++] Das PIMPL-Prinzip - Interface und Implementation trennen mit PIMPL

Und ein weiterer Quicktipp. Diesmal geht es um das PIMPL-Idiom, was eigentlich nichts anderes bedeutet, als seine Klassen (=Implementation) in einer anderen Klasse als Pointer zu halten (Pointer to IMPLementation).

Jeglicher Zugriff erfolgt dann über den Pointer in der äußeren Klasse. Klingt unsinnig? Ist es zum Glück auch meistens, in manchen Fällen braucht man aber genau das, und zwar in Fällen wie diesen:

  • Man schreibt eine Bibliothek und:
    • will bestimmte Details seiner...
Weitere Informationen zu dieser Ressource...
 

German

Well-Known Member
c-b Experte
#2
Ich hatte dank deiner Hilfe schon das Vergnügen mit PIMPL.
Bei mir war es das Problem, Namenskonflikte zu vermeiden. Ich wollte, dass die Windows-Header im Code out of scope sind. Folgender One-Liner gäbe mit Visual Studio kompiliert einen Fehler:
C++:
#include <windows.h>
#include <iostream>
#include <algorithm>

int main()
{
  std::cout << std::max(2, 3) << std::endl;
}
error C2589: '(': Ungültiges Token auf der rechten Seite von '::'
Das max Macro aus den Windows Headern beißt sich mit dem std::max aus <algorithm>. PIMPL hilft hier, wenn man die Klasse, die die Windows Header benötigt, per Pointer einbindet...
So weit also äußerst hilfreich.

Nun habe ich hier aber bei einer deiner Aussagen ein Verständnisproblem.
Man schreibt eine Bibliothek und: ... will keine Header einer Drittbibliothek mit ausliefern
:confused:
Wenn du dein Programm quelloffen auslieferst, dann mit der 3rd Party Lib. Anderenfalls wäre der Code nicht kompilierbar, oder?
Wenn du kompilierten Code auslieferst, sorgt der Linker dafür, dass auch der Code aus anderen Übersetzungseinheiten im Programm landet.
Wie muss ich das verstehen?
 

-AB-

Well-Known Member
c-b Team
c-b Experte
#3
Folgender One-Liner gäbe mit Visual Studio kompiliert einen Fehler:
Wobei bei dir ja nicht das Problem war, Funktionen, die den Windows-Header benötigen, in einer einzelnen .cpp abzulegen, sondern dass du eine Klasse haben wolltest, in der man Windows.h-spezifische Datentypen als Member halten kann (wenn ich mich richtig erinnere). Sonst hättest du kein PIMPL gebraucht ;)

Wenn du dein Programm quelloffen auslieferst, dann mit der 3rd Party Lib. Anderenfalls wäre der Code nicht kompilierbar, oder?
Wenn du kompilierten Code auslieferst, sorgt der Linker dafür, dass auch der Code aus anderen Übersetzungseinheiten im Programm landet.
Klar, wenn ich Quellcode (.cpp und Header) ausliefere, muss der 3rd Party Code auf jeden Fall mit. (Oder zumindest ein Hinweis darauf, mit welcher Lib und welcher Version derselben der Code gebaut werden soll.)

Den Quellcode mit auszuliefern ist aber im kommerziellen Bereich doch eher unüblich. Stattdessen liefere ich mit einer (dynamisch oder statisch linkbaren) Bibliothek meinen Code binär aus - aber beim Kunden würde der Compiler erstmal einen "XXX ist nicht deklariert"-Fehler werfen, bevor der Linker irgendetwas verbinden kann. Dafür liefere ich noch die entsprechenden Header-Dateien mit, in denen die verwendbaren Klassen und Funktionen deklariert sind. Jetzt kann der Linker nach Entsprechungen im Kompilat suchen. (Ist vielleicht auch einen kurzen Eintrag wert - aber nach sowas hat bisher noch niemand nachgefragt...)
 

German

Well-Known Member
c-b Experte
#4
dass du eine Klasse haben wolltest, in der man Windows.h-spezifische Datentypen als Member halten kann
Genau. Dazu musste aber windows.h im Header includiert werden. Dass ich in meinem Code keine Namenskonflikte zu erwarten hatte, wusste ich. Allerdings kann ich nicht wissen was der Benutzer der Lib in seinem Code stehen hat.

Stattdessen liefere ich mit einer (dynamisch oder statisch linkbaren) Bibliothek meinen Code binär aus
Damit habe ich mich noch nicht beschäftigt (habe es allerdings vor). Das Prinzip ist mir natürlich bekannt.
However. Jetzt macht das natürlich mehr Sinn. Unabhängig davon lieferst du den Code aber trotzdem mit, wenn auch kompiliert. Man könnte deine Aussage bspw. als Hintertür missdeuten, geschützten 3rd Party Code zu verwursten, weil er ja "nicht mit ausgeliefert" wird. Ist aber nicht so.
 

-AB-

Well-Known Member
c-b Team
c-b Experte
#5
Man könnte deine Aussage bspw. als Hintertür missdeuten, geschützten 3rd Party Code zu verwursten, weil er ja "nicht mit ausgeliefert" wird. Ist aber nicht so.
Klar, irgendwie muss der Code mit, sonst kann er nicht ausgeführt werden.
Allerdings tauchen (je nach Einstellungen und ob statisch/dynamisch) nicht alle Symbole zum Linken auf, unter Windows/VC zum Beispiel nur solche, die mit __declspec(dllexport) versehen sind. Alle anderen Funktionen/Klassen können dann auch mit Header (den man ja quasi selbst schreiben könnte, wenn man das Disassembly versteht) nicht benutzt werden. Überhaupt können die dann natürlich auch vom Compiler u.U. komplett ge-inlined werden - auch mit dem Disassember findet man dann keine Spur mehr.

Lizensierter 3rd Party Code ließe sich also tatsächlich ohne Probleme (wenn das erlaubt ist, natürlich) als Kompilat ausliefern, weil der Code eben nicht mehr rekonstruierbar ist.
 

German

Well-Known Member
c-b Experte
#6
Hmm, verstehe. Dass nicht für alles ein Name Mangling stattfindet, ist mir natürlich schon aufgefallen (um das heraus zu finden reicht ein Texteditor). Aber, wie gesagt, ich habe mich noch nicht genauer damit beschäftigt...
 
Oben