#include <iostream>

class A
{
public:
  int w;
  virtual void m1() 
  {
    std::cout << "m1 von A" << std::endl;
    m2();
  }
  
  virtual void m2()
  {
    std::cout << "m2 von A" << std::endl;
  }
};


class B 
{
public:
  int x;
  virtual void m3() = 0;
  virtual void m4 () 
  {
    std::cout << "m4 von B" << std::endl;
    m3();
    x = 5;
  }
};


class C: public A, public B
{
public:
  int y;
  virtual void m2()
  {
    std::cout << "m2 von C" << std::endl;
    y = 2;
  }

  virtual void m3()
  {
    std::cout << "m3 von C" << std::endl;
    x = 3;
  }
};


class D : public C
{
public:
  int z;
  virtual void m3() 
  {
    std::cout << "m3 von D" << std::endl;
    m1();
  }

  virtual void m5 ()
  {
    std::cout << "m5 von D" << std::endl;
    z = 4;
  }
};


int main ()
{
  A *a = new A;
  C *c = new C;
  D *d = new D;
  
  std::cout << "------------------" << std::endl;
  a->m1();
  a->m2();
  
  std::cout << "------------------" << std::endl;
  c->m1();
  c->m2();
  c->m3();
  c->m4();
  
  std::cout << "------------------" << std::endl;
  d->m1();
  d->m2();
  d->m3();
  d->m4();
  d->m5();

  delete a;
  delete c;
  delete d;
  
  // Zuweisungskompatibilitaetstest (was fuer ein Wort)
  // auskommentierte Anweisungen sind nicht zulaessig
  
  a = new C; delete a;
  a = new D; delete d;
  // a = new B;
  
  B* b;
  b = new C; delete b;
  b = new D; delete b;
  // b = new A;
  
  c = new D; delete c;
  // c = new B;
  // c = new A;
  
  // d = new C;
  // d = new B;
  // d = new A;
}

// Local Variables:
// compile-command: "g++ -Wall -pedantic -g mi.cc -o mi"
// End:

    
    
    
  
    
    
  
    
    
    
  
