| SYNOPSIS |
| object shadow(object obj, int flag) |
| |
| BESCHREIBUNG |
| Damit wird das aktuelle Objekt dem Objekt <obj> als Shadow |
| uebergeworfen. Bei Erfolg liefert es 1, sonst 0 zurueck. |
| |
| Das aufrufende Objekt muss vom Master-Objekt die Erlaubnis haben, |
| als Shadow zu wirken. Normalerweise kann einem Objekt, das |
| query_prevent_shadow() == 1 zurueck liefert, kein Shadow |
| uebergeworfen werden. In diesem Fall liefert shadow() 0 zurueck, |
| sonst das Objekt, dem der Shadow uebergeworfen wurde. |
| |
| shadow() schlaeft fehl, wenn: |
| - der Shadow vesucht, eine "nomask" definierte Funktion zu |
| ueberlagern, |
| - wenn im Praeprozessor #pragma no_shadow gesetzt ist, |
| - wenn das aufrufende Objekt bereits ein Shadow ist, |
| - wenn das aufrufende Objekt selbst einen Shadow uebergeworfen hat, |
| - wenn das aufrufende Objekt ueber ein Environment verfuegt, |
| - wenn das Zielobjekt <obj> selbst ein Shadow ist. |
| |
| Wenn ein Objekt A einem Objekt B als Shadow uebergeworfen wird, |
| werden alle call_other() Aufrufe fuer B an A umgeleitet. Wenn A die |
| Funktion, die von call_other() aufgerufen wird, nicht definiert hat, |
| wird der Aufruf an B weitergeleitet. Es gibt also nur ein Objekt, |
| welches call_other() Aufrufe fuer B machen kann: das Objekt A. Nicht |
| einmal das Objekt B kann einen call_other() auf sich selbst machen. |
| Hingegen werden alle normalen (internen) Funktionsaufrufe innerhalb |
| von B werden wie gewohnt innerhalb von B bearbeitet. |
| |
| BEISPIELE |
| Mit drei Objekten a.c, b.c und c.c: |
| |
| --- a.c --- |
| void fun() { |
| debug_message(sprintf("%O [a] fun()\n", this_object())); |
| } |
| void fun3() { |
| debug_message(sprintf("%O [a] fun3()\n", this_object())); |
| } |
| |
| --- b.c --- |
| int fun() { |
| debug_message(sprintf("%O [b] fun()\n", this_object())); |
| find_object("a")->fun(); |
| } |
| void fun2() { |
| debug_message(sprintf("%O [b] fun2()\n", this_object())); |
| find_object("a")->fun3(); |
| this_object()->fun3(); |
| } |
| |
| void do_shadow(object target) { shadow(target, 1); } |
| |
| --- c.c --- |
| int fun() { |
| debug_message(sprintf("%O [c] fun()\n", this_object())); |
| find_object("a")->fun(); |
| } |
| void fun3() { |
| debug_message(sprintf("%O [c] fun3()\n", this_object())); |
| } |
| void do_shadow(object target) { shadow(target, 1); } |
| |
| Es wird nun folgender Code aufgerufen: |
| |
| object a, b, c; |
| |
| a = load_object("a"); |
| b = load_object("b"); |
| c = load_object("c"); |
| b->do_shadow(a); |
| c->do_shadow(a); |
| debug_message("--- a->fun() ---\n"); |
| a->fun(); |
| debug_message("--- b->fun() ---\n"); |
| b->fun(); |
| debug_message("--- c->fun() ---\n"); |
| c->fun(); |
| debug_message("--- b->fun2() ---\n"); |
| b->fun2(); |
| |
| Das ergibt diesen Output: |
| |
| --- a->fun() --- |
| /c [c] fun() |
| /b [b] fun() |
| /a [a] fun() |
| --- b->fun() --- |
| /c [c] fun() |
| /b [b] fun() |
| /a [a] fun() |
| --- c->fun() --- |
| /c [c] fun() |
| /b [b] fun() |
| /a [a] fun() |
| --- b->fun2() --- |
| /b [b] fun2() |
| /a [a] fun3() |
| /c [c] fun3() |
| |
| Merke: der erste Aufruf in b::fun2() findet zuerst c::fun3()! |
| Der Grund ist, dass fuer Aufrufe aus b fuer a der Treiber |
| annimmt, dass alle Shadows vor c schon ihre Chance hatten. Der |
| zweite Aufruf hingegen ergeht an b selbst, das der Treiber als |
| vom Shadow c ueberlagert erkennt. |
| |
| GESCHICHTE |
| Bis 3.2.1@46 fuehrte die Zerstoerung eines Objekts, dem ein Shadow |
| uebergeworfen war, auch zur Zerstoerung aller seiner Shadows. |
| Seit 3.2.1@47 ueberleben Shadows die Zerstoerung des Objektes, dem |
| sie uebergeworfen sind (ausser, die wird von prepare_destruct() |
| manuell erledigt). |
| Seit LDMud 3.2.8 koenne sich Objekte dank #pragma no_shadow gezielt |
| davor schuetzen, einen Shadow uebergeworfen zu bekommen. |
| |
| SIEHE AUCH |
| query_shadowing(E), unshadow(E), query_allow_shadow(M) |