CSC448: OO Languages: C++ [3/12] Previous pageContentsNext page

====================================================
Object and static calls

class A {
public:
  int a;
  void f(int i) { }
};

instance of A:
-----------------
| int a;        |
-----------------

int main() {
  A* pa;
  pa->f(2);
}

implemented as

f__F1A(pa,2);

====================================================
Fields

class A { int a; void f(int); };
class B : A { int b; void g(int); };
class C : B { int c; void h(int); };

instance of C:
-----------------
| int a;        |
| int b;        |
| int c;        |
-----------------

====================================================
Single inheritance

class A {
  int a;
  virtual void f(int);
  virtual void g(int);
  virtual void h(int);
};
class B : A { int b; void g(int); };
class C : B { int c; void h(int); };

instance of C:
-----------------
| int a;        |     vtbl:
| vptr .............> -----------------
| int b;        |     | A::f          |
| int c;        |     | B::g          |
-----------------     | C::h          |
                      -----------------

C* pc;
pc->g(2);

implemented as

(*(pc->vptr[1])) ( pc , 2 );

====================================================
Given a C*, calling a member function of A or C is simple.
Calling a member function of B is more complex.

class A { ... };
class B { ... };

class C : A , B { ... };

is equivalent to

class C : B , A { ... };

C* pc;
pc->bf(2);  // assume that bf is a member of B
            // and that C has no member named bf
            // except the one inherited from B

becomes

bf__F1B ( (B*)((char*)pc+delta(B)) , 2 );

pc ...................>-----------------
                       |               |
                       | A part        |
                       |               |
B::bf's this .........>-----------------
                       |               |
                       | B part        |
                       |               |
                       -----------------
                       |               |
                       | C part        |
                       |               |
                       -----------------      

====================================================
casting may also involve modifying a pointer

C* pc;
B* pb;
pb = (B*)pc; // pb = (B*)((char*)pc+delta(B))
pb = pc;     // ... same
pc = (C*)pb; // pc = (C*)((char*)pb-delta(B))

comparisons too!

pc == pb; // that is,      pc == (C*)pb  //  pc == (C*)((char*)pb-delta(B))
          // equivalently, (B*)pc == pb  //  (B*)((char*)pc+delta(B)) == pb

====================================================
What about null?

C* pc;
B* pb;
pb = (B*)pc; // pb = (pc==0)?0:(B*)((char*)pc+delta(B))

====================================================
Virtual functions

class A { virtual void f(); };
class B { virtual void f(); virtual void g(); };
class C : A , B { void f(); };
A* pa = new C;
B* pb = new C;
C* pc = new C;
pa->f();  // calls C::f()
pb->f();  // calls C::f()
pc->f();  // calls C::f()

Implementation:

-----------------
|               |    vtbl:
|    vptr ..........>---------------------
|    A part     |    |  C::f | 0         |
|               |    ---------------------
-----------------
|               |    vtbl:
|    vptr ..........>---------------------
|    B part     |    |  C::f | -delta(B) |
|               |    |  B::g | 0         |
-----------------    ---------------------
|               |
|    C part     |
|               | 
-----------------

pb->f();  // call of C::f:
          // register vtbl_entry* vt = &pb->vtbl[index(f)];
          // (*vt->fct)((B*)((char*)pb+vt->delta))

struct vtbl_entry {
  void (*fct)();
  int delta;
};

====================================================
class W {
  virtual void f() { ... }
  virtual void g() { ... }
  virtual void h() { ... }
  virtual void k() { ... }
};
class AW : virtual W { void g() { ... } };
class BW : virtual W { void f() { ... } };
class CW : AW , BW { void h() { ... } };

CW* pcw = new CW;
pcw->f();        // BW::f()
pcw->g();        // AW::g()
pcw->h();        // CW::h()
((AW*)pcw)->f(); // BW::f();

      -----------------
  .........           |
  .   |    AW part    |
  .   |               |
  .   -----------------
  .........           |
  .   |    BW part    |
  .   |               |
  .   -----------------
  .   |               |
  .   |    CW part    |
  .   |               |    vtbl:
  .   -----------------    ------------------------------
  ...>|    vptr ..........>| BW::f | delta(BW)-delta(W) |
      |               |    | AW::g | -delta(W)          |
      |    W part     |    | CW::h | -delta(W)          |
      |               |    |  W::k | 0                  |
      -----------------    ------------------------------

In general, the delta stored with a function pointer in a vtbl is the
delta of the class defining the function minus the delta of the class
for which the vtbl is constructed.

====================================================
A virtual base class is inherited only once.
What does this code do without virtual inheritance?

class A { int fa; };
class B : public virtual A {
  void g() { fa++; }
  void init() { fa=0; }
};
class C : public virtual A {
  void h() { cout << fa; }
  void init() { fa=0; }
};
class D : public B, public C { };

D d; d.B::init(); d.C::init(); d.g(); d.h();

====================================================

The complexity of MI -- static checks

class A {
  int g() { return 1; }
  int f() { return 2; }
};
class B {
  int g() { return 3; }
  int f() { return 4; }
};
class C : public A, public B {
  int g() { return 5; }
};

C c;
c.f(); // Compile time error, ambiguous
c.g(); // returns 5

====================================================
class Top {
  virtual void f() { cout << "Top::f()"; }
};
class Left : public virtual Top {
  void g() { f(); }
};
class Right : public virtual Top {
  virtual void f() { cout << "Right::f()"; }
};
class Bottom : public Left, public Right { };

Bottom b; b.g(); // prints "Right::f()"
                 // with non-virtual inheritance, prints "Top::f()"

====================================================

Previous pageContentsNext page