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