shadow()
********


FUNKTION
========

   object shadow(object ob, int flag)


ARGUMENTE
=========

   object ob          - das vom shadow betroffene Objekt
   int flag           - 0 fuer eine Shadow-Existenzabfrage
                    1 fuer Shadow durch previous_object()


BESCHREIBUNG
============

   Wenn <flag> nicht 0 ist, wird das aktuelle Objekt dem Objekt obj
   als Shadow uebergeworfen. Bei Erfolg wird das geshadowte Objekt
   zurueckgegeben, sonst 0.
   Wenn <flag> 0 ist, wird entweder 0 oder das geshadowte Objekt
   zurueck gegeben.

   Wenn ein Objekt A ein Objekt B beschattet, werden alle call_other() fuer
   B auf A umgeleitet. Wenn die an B gerufene Funktion in A existiert, so
   wird sie in A gerufen, bei Nichtexistenz in B.
   A ist das einzige Objekt, welche die beschatteten Funktionen mit
   call_other() in B aufrufen kann, selbst B kann nicht per call_other()
   diese Funktion rufen.
   Alle intern verwendeten Funktionen arbeiten jedoch weiterhin normal.

   Das aufrufende Objekt muss vom Master-Objekt die Erlaubnis haben,
   als Shadow zu wirken.

   Es gibt folgende Kriterien fuer eine erfolgreiche Beschattung:
   - das zu beschattende Objekt ob:
     - ist weder ein access_rights-Objekt noch ein ROOT-Objekt
     - gibt beim Aufruf von query_prevent_shadow(beschatter) eine 0
       zurueck
     - beschattet selbst niemanden
     - hat kein '#pragma no_shadow' gesetzt
   - der Beschatter:
     - wird nicht selbst (direkt) beschattet
     - beschattet noch niemanden (sonst folgt direkter Abbruch)
     - hat kein environment()
     - definiert/beschattet keine Methode, die im beschatteten Objekt ob
       als nomask definiert ist

   Beschattet man ein Objekt A mit einem Objekt B und dann das Objekt A
   zusaetzlich mit einem Objekt C, so wird eine Beschattungshierarchie
   erstellt:

   B macht shadow(A, 1)
   B->A
   C macht shadow(A, 1)
   C->B->A


BEISPIELE
=========

   // wenn: B beschattet A, dann
   shadow(find_object(A), 0) == B


   // 3 Objekte beschatten in Hierarchie (liegt auch im Pfad)
   --- aa.c ---
   void fun() {
       printf("%O [a] fun()\n", this_object());
   }

   void fun3() {
       printf("%O [a] fun3()\n", this_object());
   }

   --- bb.c ---
   int fun() {
       printf("%O [b] fun()\n", this_object());
       find_object("/doc/beispiele/shadow/aa")->fun();
   }

   void fun2() {
       printf("%O [b] fun2()\n", this_object());
       find_object("/doc/beispiele/shadow/aa")->fun3();
       this_object()->fun3();
   }

   void do_shadow(object target) { shadow(target, 1); }

   --- cc.c ---
   int fun() {
       printf("%O [c] fun()\n", this_object());
       find_object("/doc/beispiele/shadow/aa")->fun();
   }

   void fun3() {
       printf("%O [c] fun3()\n", this_object());
   }

   void do_shadow(object target) { shadow(target, 1); }

   // darauf arbeitender Code

   object a, b, c;

   destruct("/doc/beispiele/shadow/aa");
   a = load_object("/doc/beispiele/shadow/aa");
   destruct("/doc/beispiele/shadow/bb");
   b = load_object("/doc/beispiele/shadow/bb");
   destruct("/doc/beispiele/shadow/cc");
   c = load_object("/doc/beispiele/shadow/cc");

   b->do_shadow(a);
   c->do_shadow(a);
   printf("--- a->fun() ---\n");
   a->fun();
   printf("--- b->fun() ---\n");
   b->fun();
   printf("--- c->fun() ---\n");
   c->fun();
   printf("--- b->fun2() ---\n");
   b->fun2();

   // ... und seine Ausgabe:

   --- a->fun() ---
   /doc/beispiele/shadow/cc [c] fun()
   /doc/beispiele/shadow/bb [b] fun()
   /doc/beispiele/shadow/aa [a] fun()
   --- b->fun() ---
   /doc/beispiele/shadow/cc [c] fun()
   /doc/beispiele/shadow/bb [b] fun()
   /doc/beispiele/shadow/aa [a] fun()
   --- c->fun() ---
   /doc/beispiele/shadow/cc [c] fun()
   /doc/beispiele/shadow/bb [b] fun()
   /doc/beispiele/shadow/aa [a] fun()
   --- b->fun2() ---
   /doc/beispiele/shadow/bb [b] fun2()
   /doc/beispiele/shadow/aa [a] fun3()
   /doc/beispiele/shadow/cc [c] fun3()

   // Der erste Aufruf von b::fun2() in a findet sofort a::fun3()! Der
   // Driver nimmt an, dass alle Shadows ab c bei Rufen von b nach a
   // schon ihre Chance hatten.
   // Der zweite Aufruf allerdings ist auf b und wird beim Durchgeben
   // an a von c uebernommen.


SIEHE AUCH
==========

   Generell:       shadow(E)
   Rechte:         query_allow_shadow(M), query_prevent_shadow(L)
   Informationen:  query_shadowing(E)

8.Aug 2007 Gloinson
