Grundlegende Fragen über das Design einer Shared Library in C++ mit Java im Hinterkopf
-
Hallo zusammen
Ich hatte letzte Woche einen betrieblichen Kurs über Java-OOP und mir sind da einige Fragen betreffend Library Design in C++ aufgekommen.
Zuerst was mir im Java-Kurs auffiel:
- Java bietet package protected an, was eine Verwendung einer Klasse ausserhalb des Packages verunmöglicht
- Die Hautpklasse der Library wird als Singleton mir einer Factory verwendet
- Für jedes Businessobjekt, dass ausserhalb der Bibliothek verwendet wird, gibt es ein Interface. Die eigentliche Businessklasse wird dann auf package protected gesetzt
- Sind mehrere Businessobjekte ähnlich, wird eine abstrakte Klasse geschrieben, welche über ein Interface verwendbar ist. Businessobjekte sind von der abstrakten Klasse abgeleitet (und Package protected, da das Interface öffentlich ist)
- Verschiedene Businessobjekte verweden über verschiedene create Methoden in der Factory erstellt, zB Factory.createFoo() erstellt intern ein Foo Objekt, liefert aber ein Interface Objekt zurückNun, mit diese Erkenntnisen ging ich heim und es entstanden in meinem Kopf diverse Fragen, da ich momentan selber plane, eine C++ Shared Libary zu schreiben:
- Wenn ich mir Tutorials über Shared Libraries anschaue sehe ich nie Interfaces ? Warum ? Verlässt man sich immer auf Compiler Attribute zum exportieren der Klasse ? Schlussendlich muss man ohne Interface trotzdem die ganze Businessklasse exportieren, um sie verwenden zu können ?
- Als nachfolgende Frage auf Frage 1: Ist es üblich, ein öffentliches/zu exportierendes Interface zu schreiben und die Libraryklasse innerhalb der Library zu hidden oder handelt es sich hier wirklich um eine Java Lösung?
- Kennt jemand ein Beispiel, wie man richtige Shared Libraries mit Businessobjekten schreibt (Welche dann vielleicht auch gleich meine gesamten Fragen beantwortet)
- Eine Interfaces Klasse mit virtuellen Methoden ist ja im eigentlichen Sinne unfähig, ein Objekt zu instanzierenIn meinem Kopf hat sich dann folgendes Schema aufgebaut, um eine C++ Shared Library zu entwickeln:
- SharedLibraryFactory: Singleton-Klasse mit Factory, um intern ObjectFoo und ObjectBar zu erstellen, ObjectInterface wird bei beiden zurückgeliefert. Wird exportiert
- ObjectInterface: Interface für die Objekte. Wird exportiert
- ObjectFoo: Businessklasse Foo, abgeleitet von ObjectInterface. Wird nicht exportiert
- ObjectBar: Businessklasse Bar, abgeleitet von ObjectInterface. Wird nicht exportiertLiege ich mit dieser Überlegung richtig ? Ich möchte noch anfügen, dass ich die Library zur Compilezeit dazulinke, sprich ich sie nicht mit dlopen/LoadLibrary dynamisch laden & resolven muss.
Freundliche Grüsse,
Simon
-
swaechter schrieb:
In meinem Kopf hat sich dann folgendes Schema aufgebaut, um eine C++ Shared Library zu entwickeln:
- SharedLibraryFactory: Singleton-Klasse mit Factory, um intern ObjectFoo und ObjectBar zu erstellen, ObjectInterface wird bei beiden zurückgeliefert. Wird exportiert
- ObjectInterface: Interface für die Objekte. Wird exportiert
- ObjectFoo: Businessklasse Foo, abgeleitet von ObjectInterface. Wird nicht exportiert
- ObjectBar: Businessklasse Bar, abgeleitet von ObjectInterface. Wird nicht exportiertWenn du es so umsetzt, dann nimm Java oder C#. Du wirst dich bald über fehlende Reflection aufregen und mit korruptem Speicher zu kämpfen haben.
In C++ macht das so jedenfalls keinen Sinn.
-
Hi
Nein, ich möchte nicht auf Java/C# wechseln, da ich gewisse C++ Frameworks verwende. Mir geht es darum zu wissen, wie man eine saubere Shared Library schreibt, welche Businessobjekte mit dem Verwender austauscht, ohne dass dieser Zugriff auf die komplette Implementierung hat und mit dieser Unfug anstellen könnte (Zum Beispiel eigene Objekte erstellen, ohne diese per Factory erstellen zu lassen).
Gruss
-
swaechter schrieb:
- Java bietet package protected an, was eine Verwendung einer Klasse ausserhalb des Packages verunmöglicht
C++ kennt keine Packages.
swaechter schrieb:
- Die Hautpklasse der Library wird als Singleton [...]
pfui, Finger weg von Singleton. Auch wenn dies möglicherweise einer der extrem seltenen Fälle ist, wo man zumindest ein wenig argumentieren könnte, dass Singleton nicht zu 100% völlig daneben ist...
swaechter schrieb:
- Wenn ich mir Tutorials über Shared Libraries anschaue sehe ich nie Interfaces ? Warum ? Verlässt man sich immer auf Compiler Attribute zum exportieren der Klasse ? Schlussendlich muss man ohne Interface trotzdem die ganze Businessklasse exportieren, um sie verwenden zu können ?
C++ kennt weder Shared Libraries, noch ein portables Objektlayout. Klassen in eine Shared Library exportieren, ist ein völlig compiler- und plattformspezifisches Feature. Deine Library funktioniert dann nur unter ganz bestimmten Umständen mit genau diesem einen Compiler auf genau dieser einen Plattform. Wenn man mehr will als das, muss man sich auf den entsprechenden kleinsten gemeinsamen Nenner beschränken, was in der Regel auf ein prozedurales Interface (C-Style) rausläuft.
swaechter schrieb:
- Eine Interfaces Klasse mit virtuellen Methoden ist ja im eigentlichen Sinne unfähig, ein Objekt zu instanzieren
Du kannst auch in Java keine Interfaces instanzieren...
swaechter schrieb:
In meinem Kopf hat sich dann folgendes Schema aufgebaut, um eine C++ Shared Library zu entwickeln:
- SharedLibraryFactory: Singleton-Klasse mit Factory, um intern ObjectFoo und ObjectBar zu erstellen, ObjectInterface wird bei beiden zurückgeliefert. Wird exportiert
- ObjectInterface: Interface für die Objekte. Wird exportiert
- ObjectFoo: Businessklasse Foo, abgeleitet von ObjectInterface. Wird nicht exportiert
- ObjectBar: Businessklasse Bar, abgeleitet von ObjectInterface. Wird nicht exportiertLiege ich mit dieser Überlegung richtig ? Ich möchte noch anfügen, dass ich die Library zur Compilezeit dazulinke, sprich ich sie nicht mit dlopen/LoadLibrary dynamisch laden & resolven muss.
Das geht schon in eine nicht ganz so falsche Richtung. Rein virtuelle Interface Klassen an dll Grenzen sind ein für viele Anwendungen brauchbarer Kompromiss (Dinge wie z.B. STL Container gehören aber nicht in das Interface). Wenn du sowieso statisch bindest, kannst du aber auch das ganze Klassen exportieren Zeug machen, man muss nur ein wenig aufpassen dabei. Ansonsten gibt es unter Windows z.B. auch COM, das wäre die ganz proper solution.
Auch wenn beide geschwungene Klammern verwenden: C++ ist nicht Java. Die beiden Sprachen sind extrem unterschiedlich. Ich würde empfehlen, dich erstmal von Grund auf tiefgehend mit C++ zu beschäftigen, ansonsten wirst du sehr wahrscheinlich einfach nur in C++ Java coden...
-
In C++ schreibt man zwei Klassen ObjectFoo und ObjectBar.
-
Nathan schrieb:
In C++ schreibt man zwei Klassen ObjectFoo und ObjectBar.
Leider bleiben damit folgende Fragen unbeantwortet:
- Wie schützte ich ObjectFoo und ObjectBar vor einer Instanzierung durch den Benutzer. Beide Klassen sollten nur durch eine Helperklasse (In diesem Fall die Factory) erstellbar sein, ansonsten können die Klassen missbraucht werden. ObjectFoo und ObjectBar sind wirklich reine Businessobjekte, sprich enthalten Daten und nicht wirklich Logik. Folglich möchte ich diese Objekte nur durch die Faktory verändern lassen (welche die Eingabe/Veränderung dann auch prüft)
- Was hide und was exportiere ich ? Ich möchte die Implementierung/Logik ja nicht exportieren, sondern nur die Schnittstelledot schrieb:
Auch wenn beide geschwungene Klammern verwenden: C++ ist nicht Java. Die beiden Sprachen sind extrem unterschiedlich. Ich würde empfehlen, dich erstmal von Grund auf tiefgehend mit C++ zu beschäftigen, ansonsten wirst du sehr wahrscheinlich einfach nur in C++ Java coden...
Den Gedanken habe ich auch oft. Mein Problem ist, dass ich eigentlich mit Qt zu C++ gekommen bin und nie wirklich mit C/C++, Hello World (Respektive Grundlegenden Sachen) als "Vanilla" angefangen habe. Es fällt mir jetzt recht schwer, wieder ohne Qt auszukommen, da mir dieses Framework einfach soviele praktische Features offeriert
dot schrieb:
pfui, Finger weg von Singleton. Auch wenn dies möglicherweise einer der extrem seltenen Fälle ist, wo man zumindest ein wenig argumentieren könnte, dass Singleton nicht zu 100% völlig daneben ist...
Geb ich dir vollkommen Recht. Ist jetzt rausgeworfen. Klasse wird einmal instanziert.
dot schrieb:
Ansonsten gibt es unter Windows z.B. auch COM, das wäre die ganz proper solution.
Kann ich leider nicht verwenden, ich möchte den Sourcecode plattformunabhängig halten. Darum verwende ich auch Frameworks (Unter anderem wie gesagt Qt). Defines für MSVC/gcc/clang exports wie cdecl oder atribute gehen aber vollkommen ok und gehören halt einfach dazu
Betreffend Factory/Interface/Export bin ich jetzt bei sowas gelandet (Was denke ich deiner Vorstellung entspricht ?). Jedenfalls funktioniert die LIBRARY_PRIVATE noch nicht - Defines für die Library wird gesetzt, bei der Applikation wird es weggelassen - soweit sollte es also hin kommen ?. Ich bin mir auch noch nicht ganz sicher ob das betreffend Vererbung überhaupt möglich ist:
main.cpp
#include <iostream> #include "library/ObjectExport.h" #include "library/ObjectFactory.h" #include "library/ObjectInterface.h" int main(void) { // Arbeitet wie gewünscht/gedacht ObjectFactory *factory = new ObjectFactory(); ObjectInterface *objectfoo = factory->createFoo(); ObjectInterface *objectbar = factory->createBar(); std::cout << "Factory:" << factory->getNumberAsCheck() << std::endl; std::cout << "ObjectFoo:" << objectfoo->getNumber() << std::endl; std::cout << "ObjectBar:" << objectbar->getNumber() << std::endl; delete objectfoo; delete objectbar; delete factory; // Dieses Szenarie gilt es zu verhindern (Funktioniert aber noch ...) ObjectFoo *abusedobject = new ObjectFoo(); std::cout << "AbusedObject:" << abusedobject->getNumber() << std::endl; delete abusedobject; return 0; };ObjectFactory.h
#ifndef OBJECTFACTORY_H #define OBJECTFACTORY_H #include "ObjectExport.h" #include "ObjectInterface.h" #include "ObjectFoo.h" #include "ObjectBar.h" class LIBRARY_EXPORT ObjectFactory { public: int getNumberAsCheck(); ObjectInterface *createFoo(); ObjectInterface *createBar(); }; #endif // OBJECTFACTORY_HObjectFactory.cpp
#include "ObjectFactory.h" int ObjectFactory::getNumberAsCheck() { return 9001; } ObjectInterface *ObjectFactory::createFoo() { return new ObjectFoo(); } ObjectInterface *ObjectFactory::createBar() { return new ObjectBar(); }ObjectInterface.h
#ifndef OBJECTINTERFACE_H #define OBJECTINTERFACE_H #include "ObjectExport.h" class LIBRARY_EXPORT ObjectInterface { public: virtual int getNumber() = 0; }; #endif // OBJECTINTERFACE_HObjectFoo.h (ObjectBar.h ist gleich)
#ifndef OBJECTFOO_H #define OBJECTFOO_H #include "ObjectExport.h" #include "ObjectInterface.h" class LIBRARY_PRIVATE ObjectFoo : public ObjectInterface { public: int getNumber() { return 41; } }; #endif // OBJECTFOO_HObjectExport.h (Momentan einfach mal für Linux GCC, Rest kommt wenn der Prototyp funktioniert)
#ifndef OBJECTEXPORT_H #define OBJECTEXPORT_H #if defined(COMPILER_GCC) #define LIBRARY_EXPORT __attribute__ ((visibility ("default"))) #define LIBRARY_PRIVATE __attribute__ ((visibility ("hidden"))) #else #define LIBRARY_EXPORT #define LIBRARY_PRIVATE #endif #endif // OBJECTEXPORT_HGruss
-
swaechter schrieb:
Nathan schrieb:
In C++ schreibt man zwei Klassen ObjectFoo und ObjectBar.
Leider bleiben damit folgende Fragen unbeantwortet:
- Wie schützte ich ObjectFoo und ObjectBar vor einer Instanzierung durch den Benutzer. Beide Klassen sollten nur durch eine Helperklasse (In diesem Fall die Factory) erstellbar sein, ansonsten können die Klassen missbraucht werden. ObjectFoo und ObjectBar sind wirklich reine Businessobjekte, sprich enthalten Daten und nicht wirklich Logik. Folglich möchte ich diese Objekte nur durch die Faktory verändern lassen (welche die Eingabe/Veränderung dann auch prüft)Konstruktoren. Memberfunktionen.
-
swaechter schrieb:
- Wie schützte ich ObjectFoo und ObjectBar vor einer Instanzierung durch den Benutzer. Beide Klassen sollten nur durch eine Helperklasse (In diesem Fall die Factory) erstellbar sein, ansonsten können die Klassen missbraucht werden.
Dann exportier sie einfach nicht. Wenn du sie nicht exportierst und dem User keine Deklaration der Klassen im Header deiner Library lieferst, bekommt der nichtmal mit, dass sie existieren. Überhaupt: Sowas wie Klassen gibt's sowieso nur im Source Code. Die fertig kompilierte Library enthält keinerlei Informationen über irgendwelche "Klassen" oder sonstwas, dort drin gibt's einfach nur einen Haufen Maschinencode.
swaechter schrieb:
dot schrieb:
Auch wenn beide geschwungene Klammern verwenden: C++ ist nicht Java. Die beiden Sprachen sind extrem unterschiedlich. Ich würde empfehlen, dich erstmal von Grund auf tiefgehend mit C++ zu beschäftigen, ansonsten wirst du sehr wahrscheinlich einfach nur in C++ Java coden...
Den Gedanken habe ich auch oft. Mein Problem ist, dass ich eigentlich mit Qt zu C++ gekommen bin und nie wirklich mit C/C++, Hello World (Respektive Grundlegenden Sachen) als "Vanilla" angefangen habe. Es fällt mir jetzt recht schwer, wieder ohne Qt auszukommen, da mir dieses Framework einfach soviele praktische Features offeriert
Nun, der von dir gepostete Code zeig die typischen Symtome: Überall wird new benutzt, sogar roh, alles wird per Referenz herumgereicht. Das ist halt genau, wie man es in Java macht, weil es dort nicht besser geht. Ein C++ Programmierer würde deine ObjectFactory z.B. nicht per new anlegen. Ein lokales Objekt tut's dort genauso. Ansonsten würde man Besitzverhältnisse über std::unique_ptr modellieren, anstatt mit rohen Zeigern und new. Dann spart man sich auch das ganze herumdeleten und alles ist automatisch exception-safe. Das Stichwort dabei lautet RAII und ist wohl eines der mächtigsten Feature von C++ überhaupt.
ACHTUNG: Vorsicht mit RAII! Wenn du RAII einmal verstanden hast, wirst du diese Welt niemals mehr verlassen wollen, jede andere Sprache wird dir mangels RAII früher oder später auf die Nerven gehen und jeder Kontakt mit Garbage Collection wird dich an den Punkt bringen, wo du dir am liebsten die Augen auskratzen würdest.

-
dot schrieb:
Dann exportier sie einfach nicht. Wenn du sie nicht exportierst und dem User keine Deklaration der Klassen im Header deiner Library lieferst, bekommt der nichtmal mit, dass sie existieren. Überhaupt: Sowas wie Klassen gibt's sowieso nur im Source Code. Die fertig kompilierte Library enthält keinerlei Informationen über irgendwelche "Klassen" oder sonstwas, dort drin gibt's einfach nur einen Haufen Maschinencode.
Ok, ich hatte das total falsch im Kopf. Der Datenheader wird dem Verwender ja nicht zur Verfügung gestellt. Soweit also ok
Betreffend RAII & (Smart) Pointern: Ist mir bewusst, aber es handelt sich hier nur um einen Prototypen. Ich sollte in Zukunft aber trotzdem mehr Wert auf Smart Pointers legen (RAII verwende ich wo es nur geht, ich habe einfach Angst, ich sprenge einmal den Stack)
Betreffend der ursprünglichen Frage: Die ist soweit gelöst, da ich auch auf das Thema PIMPL und/vs Abstract Interface gestossen bin. Ich werde die Factoryklasse wahrscheinlich mit dem PIMPL Gedanken realisieren und für die Businessobjekte Interfaces (also abstrakte Interfaces) zurückgeben.
-
Ist das zu viel verlangt, einfach die Konstruktoren zur korrekten Erzeugung zu nutzen und via Memberfunktionen die Daten wegzukapseln?
Ganz ohne Factory. Und ohne PIMPL, dessen Sinn und Zweck es eigentlich ist, nicht alle bneötigten Header zu inkludieren.
Und RAII hat keine Nachteile, die den "Stack sprengen könnten".
-
Nathan schrieb:
Ist das zu viel verlangt, einfach die Konstruktoren zur korrekten Erzeugung zu nutzen und via Memberfunktionen die Daten wegzukapseln?
Ganz ohne Factory. Und ohne PIMPL, dessen Sinn und Zweck es eigentlich ist, nicht alle bneötigten Header zu inkludieren.
Und RAII hat keine Nachteile, die den "Stack sprengen könnten".Nathan, mir bringt es leider nicht viel, wenn Du sagst: Mach es so, so und so, lass dies und jenes weg. Was mir wichtig ist:
- Warum so und nicht anderst ? Was ist sind deine Beweggründe, dies so zu realiseren ?
- Betreffend Header und exportieren einzelner Funktionen: Der Verwender hat ja dann doch den Header der Implementierung (Was ich nicht will). Wenn ich was falsch verstehe, mach doch bitte schnell ein Codebeispiel
- (Off Topic): Was passiert wenn ich mehrere grosse Listen auf den Stack werfe. Der Stack hat doch eine vom System vorgeschrieben [Vor dem Start änderbare] Grösse ?Gruss Simon
-
swaechter schrieb:
Nathan schrieb:
Ist das zu viel verlangt, einfach die Konstruktoren zur korrekten Erzeugung zu nutzen und via Memberfunktionen die Daten wegzukapseln?
Ganz ohne Factory. Und ohne PIMPL, dessen Sinn und Zweck es eigentlich ist, nicht alle bneötigten Header zu inkludieren.
Und RAII hat keine Nachteile, die den "Stack sprengen könnten".- Warum so und nicht anderst ? Was ist sind deine Beweggründe, dies so zu realiseren ?
Man spart sich Programmierarbeit, wenn man nur Klassen ohne Factory hat.
- Betreffend Header und exportieren einzelner Funktionen: Der Verwender hat ja dann doch den Header der Implementierung (Was ich nicht will). Wenn ich was falsch verstehe, mach doch bitte schnell ein Codebeispiel
Es wäre einfacher wenn du sagen würdest, was deine Klassen machen.
Nur mit dem jetzigen Beispiel lässt sich nur schwer Code zeigen.
Und ja, wenn du private Daten von einem Typ hast, die keine Pointer sind, muss der Header inkludiert werden. Aus rein programmiertechnischer Sicht ist das kein Problem, da der Client eh nicht (diverse Tricks jetzt mal außen vor gelassen) darauf zugreifen kann. Höchstens aus Wartungsgründen, da er dann recompilen muss, wenn sich die Implementierung ändert. Und deswegen gibt es PIMPL.- (Off Topic): Was passiert wenn ich mehrere grosse Listen auf den Stack werfe. Der Stack hat doch eine vom System vorgeschrieben [Vor dem Start änderbare] Grösse ?
RAII ist nicht "schmeiß alles auf dem Stack", RAII ist "lass Destruktoren aufräumen". Aber solange es keinen Grund gibt, etwas auf dem Heap zu werfen, lass es auf dem Stack. Der ist groß genug.
-
Nathan schrieb:
Es wäre einfacher wenn du sagen würdest, was deine Klassen machen.
Was ich im Kopf habe (Als Klassen):
- Platform: Kann Projekte erstellen/editieren/löschen und den Projekten Einträge hinzufügen/editieren/entfernen
- Project: Beinhaltet Name und Einträge als Liste
- Entry: Beinhaltet einen (Key)Namen und BeschreibungNun, Gedanken betreffend der Platform:
- Die Platform übernimmt das Inputchecking
- Der Verwender muss die Platform verwenden, um Projekte und Einträge ändern zu können
- Project und Entry sollen als reine Datenobjekte dienen, sprich keine Logik enthalten (Darum auch die Bearbeitung über die Platform)Wenn Du mir einen anderen Weg aufzeigen kannst, sowas zu realiseren, her damit

-
Also in etwa so?
struct project {...}; struct entry {...}; class platform { public: add_or_change_entry(size_t index, entry e); add_or_change_project(size_t index, project p); private: container projects_; container entrys_; };Was spricht dagegen, dass genau so zu machen?
Edit: Mit entry in project, hatte das überlesen.
-
Genau, etwas in der Art. Nun möchte ich aber die Implementierung von der Schnittstelle abtrennen, um zum Beispiel beim Hinzufügen/Änderung von privaten Attributen in der Implementierung nicht gleich das ganze Offset zu verschieben (Bin auf dem Gebiet neu & daran mich einzulesen).
Nun war meine Idee:
- Öffentliche Klasse besitzt einen Pointer zu der libraryinternen Implementierung
- Methodenzugriffe auf die öffentliche Klasse werden an die Implementierung weitergeleitet, diese arbeitet die Sache ab
- Änderungen in der Implementuerung machen eine Neukompilierung der Applikation mit der (neuen) Library überflüssig ?Oder habe ich da was falsch verstanden ? An dieser Stelle könnte ich doch das PIMPL Pinzip verwenden ?
Gruss Simon
-
swaechter schrieb:
Nun möchte ich aber die Implementierung von der Schnittstelle abtrennen, um zum Beispiel beim Hinzufügen/Änderung von privaten Attributen in der Implementierung nicht gleich das ganze Offset zu verschieben (Bin auf dem Gebiet neu & daran mich einzulesen).
Wozu? Wo liegt das Problem, wenn sich das Layout der Membervariablen ändert?
Was du beschreibst, ist gerade das PImpl-Idiom. Wie erwähnt wird es primär zur Verringerung von Compilezeit-Abhängigkeiten eingesetzt.
-
Nexus schrieb:
Wozu? Wo liegt das Problem, wenn sich das Layout der Membervariablen ändert?
Klar könnte ich darauf verzichten und immer davon ausgehen, dass Applikation und Library neu kompiliert & gelinkt werden, aber eventuell möchte ich das eines Tages ändern und dann alles umbauen, nur um das zu erreichen ? Lieber fange ich dann gleich richtig an und setze auf eine lose Kopplung zwischen Implementierung und Schnittstelle
Betreffend Businessobjekten: Gibt es da auch eine gute Möglichkeit, eine lose Kopplung zu erreichen oder schreibt man einfach eine Klasse, bestehend aus lauter virtuellen Funktionen und das eigentliche (interne) Businessobjekt erbt davon ? PIMPL würde in einem solchen Fall ja einen enormen Overhead generieren (Was mehr auffällt als bei einer Klasse, die aus lauter Logik besteht und Inpputchecking betreibt) ?
-
swaechter schrieb:
Klar könnte ich darauf verzichten und immer davon ausgehen, dass Applikation und Library neu kompiliert & gelinkt werden, aber eventuell möchte ich das eines Tages ändern und dann alles umbauen, nur um das zu erreichen ? Lieber fange ich dann gleich richtig an und setze auf eine lose Kopplung zwischen Implementierung und Schnittstelle
Nachträglich pimpl einfügen? Das ist quasi umsonst, da muss ja nicht einmal die Schnittstelle geändert werden.
PIMPL würde in einem solchen Fall ja einen enormen Overhead generieren
lol
-
justlol schrieb:
swaechter schrieb:
Klar könnte ich darauf verzichten und immer davon ausgehen, dass Applikation und Library neu kompiliert & gelinkt werden, aber eventuell möchte ich das eines Tages ändern und dann alles umbauen, nur um das zu erreichen ? Lieber fange ich dann gleich richtig an und setze auf eine lose Kopplung zwischen Implementierung und Schnittstelle
Nachträglich pimpl einfügen? Das ist quasi umsonst, da muss ja nicht einmal die Schnittstelle geändert werden.
PIMPL würde in einem solchen Fall ja einen enormen Overhead generieren
lol
Danke für deinen sehr konstruktiven Beitrag. Wenn Du schon solchen Content schreibst, registrier dich doch bitte, dass man dich erkennen kann (und ich dir konkret aus dem Weg gehen kann)
Betreffend PIMPL nachträglich einfügen:
1.) Was muss nicht mehr eingefügt werden ? Sollte es wie in Frage 2 sein hast Du definitiv kein PIMPL...
2.) Nein sicher nicht. Hast Du eine Klasse, in welcher gewisse Methoden exportiert und andere nicht exportiert werden, verschiebt sich dein Offset immer, wenn Du gewisse Bestandteile änderst (Methoden/Attribute etc). Das ist nicht gerade das, was ich anstrebe (Betreffend loser Kopplung).Vorherige Frage steht immer noch im Raum
-
Binärschnittstellen in C++ sind sowieso eine Angelegenheit für sich. Du bist wegen fehlendem standardisierten ABI relativ eingeschränkt und oft zum Neukompilieren gezwungen (spätestens wenn du den Compiler oder nur schon die Version oder bestimmte Flags wechselst).
Du solltest dir also überlegen, wie weit du deswegen dein Design verkomplizieren willst.