Mitmischer 1703 - Di 03.04.12 11:12
Titel: late late binding
Mir ist kein besserer Begriff dafür eingefallen, deswegen habe ich es einfach mal "late late binding" genannt. Mein Problem ist folgendes:
Ich habe zwei Klassen gleichen Namens, die dasselbe Interface aber eine unterschiedliche Implementierung aufweisen und baue mir die Bibliotheken Implementation1.dll und Implementation2.dll. In einem anderen Programm möchte ich zwischen Implementation1.dll und Implementation2.dll wechseln können. Wichtig ist mir dabei, dass ich den aufrufenden Code
nicht mehrmals schreiben muss:
Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23:
| // Implementation1.dll class Klasse { void foo(int bar); int boo(void* far); }
// Implementation2.dll class Klasse { void foo(int bar); int boo(void* far); }
// aufrufender Code void DoSomethingComplicated() { // ... // aufrufender Code existiert nur einmal Klasse kl; kl.foo(42); // ... } |
Falls mein Vorhaben mit Klassen nicht möglich ist, wie sieht es mit einfachen Funktionen aus? Weiterhin soll das ganze wenn möglich auch unter Linux lauffähig sein, daher wäre es schön, wenn möglichst wenig WinAPI zum Einsatz käme.
Grüße,
Mitmischer
Th69 - Di 03.04.12 11:56
Hallo,
du programmierst in C++, oder?
Du solltest dafür dann eine abstrakte Klasse (pure virtual interface) deklarieren:
Quelltext
1: 2: 3: 4: 5:
| class Base { virtual void foo(int bar) = 0; virtual int boo(void* far) = 0; }; |
Und deine Implementationen sollten davon erben.
Dann kannst du die DLLs zur Laufzeit austauschen - bedenke jedoch, daß du dann für alle DLLs sowie den aufrufenden Code immer mit
demselben Compiler kompilieren mußt (denn C++ verfügt nicht über eine genormte
ABI [
http://de.wikipedia.org/wiki/Bin%C3%A4rschnittstelle]).
P.S: Ich sehe gerade, daß du die Klasse direkt im Code instanziierst. Dies geht dann natürlich nicht mehr, d.h. am besten du definierst dir dann eine Factory-Methode, welche eine Instanz der jeweiligen Klasse (per new) erzeugt.
Ich bin mir nicht mehr sicher, aber es kann sein, daß du auch explizit den Destruktor deklarieren als auch definieren mußt (evtl. sogar direkt als erste Funktion der Klasse):
Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| class Base { virtual ~Base();
// ... };
inline Base::~Base() { } |
(ist schon ein paar Jahre her, als ich dies das letzte mal programmiert hatte)