Method Address

NOTE: Legend of colors for this twiki:

  Shell commands  (cut & paste)
  Sample shell output
  Python configuration files  (cut & paste)
  C++ code  (cut & paste)

Here is a piece of C++ code that illustrates the difference between virtual and non-virtual methods.

// What is the method address in a derived class instence
// for a virtual and a non-virtual method?

#include <iostream>
#include <stdio.h>

using namespace std;

//_____________________________________________________________________________
class A {
public:
  void hello() { cout << "A: hello, world!" << endl; }
  void bye() { cout << "A: adios amigos!" << endl; }
};


//_____________________________________________________________________________
class B : public A {
public:
  /// This method shadows A::hello!
  void hello() { cout << "B: non-virtual hell, oh!" << endl; }
  /// No implementation of bye!
};


//_____________________________________________________________________________
class C {
public:
  virtual void hello() { cout << "C: hello!" << endl; }
  virtual void bye() { cout << "C: adios amigos!" << endl; }
};


//_____________________________________________________________________________
class D : public C{
public:
  virtual void hello() { cout << "D: virtual hell, oh!" << endl; }
  virtual void bye() { cout << "D: virtual hell, oh!" << endl; }
};


//_____________________________________________________________________________
int main(int argc, char** argv)
{  
  
  /// Print legend
  cout << "X * x = new X(); // X = A, C" << endl;
  cout << "X * xy = new Y(); // Y = B, D; Y derived from X" << endl;
  cout << "A::hello(), A::bye() are non-virtual" << endl;
  cout << "C::hello(), C::bye() are virtual" << endl;
  cout << "B::hello() re-implemented" << endl;
  cout << "B::bye() not implemented, only inherited from A" << endl;
  cout << endl;

  A * a = new A();
  B * b = new B();
  C * c = new C();
  D * d = new D();

  A * ab = new B();
  C * cd = new D();

  /// Sanity check
  cout << "x->hello();" << endl;
  cout << "x=a: "; a->hello();
  cout << "x=b: "; b->hello();
  cout << "x=c: "; c->hello();
  cout << "x=d: "; d->hello();
  cout << endl;
  
  cout << "x->bye();" << endl;
  cout << "x=a: "; a->bye();
  cout << "x=b: "; b->bye();
  cout << "x=c: "; c->bye();
  cout << "x=d: "; d->bye();
  cout << endl;

  /// Now the trickier part
  /// Here, ab behaves differently than cd!
  cout << "xy->hello();" << endl;
  cout << "xy=ab: "; ab->hello();  /// Calls the base class implementation.
  cout << "xy=cd: "; cd->hello();  /// Calls the derived class implementation.
  cout << endl;
  
  cout << "((Y*) xy)->hello();" << endl;
  cout << "xy=ab: "; ((B*) ab)->hello();
  cout << "xy=cd: "; ((C*) cd)->hello();
  cout << endl;

  /// Here, ab->bye() behaves differently than ab->hello()!
  cout << "xy->bye();" << endl;
  cout << "xy=ab: "; ab->bye();
  cout << "xy=cd: "; cd->bye();
  cout << endl;
  
  cout << "((Y*) xy)->bye();" << endl;
  cout << "xy=ab: "; ((B*) ab)->bye();
  cout << "xy=cd: "; ((C*) cd)->bye();
  cout << endl;

  delete a;
  delete b;
  delete c;
  delete d;
  delete ab;
  delete cd;

  return 0;
}

Virtual methods may be changed in the derived classes, e.g. D::hello() provides a new implementation of C::hello(). So may be the non-virtual methods, like B::hello() provides a new implementation of A::hello().

A call to a non-virtual method in the derived class (b->hello(); b->bye();) is resolved based on whether it is re-implemented in the derived class (like B::hello(), then the re-implementation is used), or not (like B::bye(), then the only available implementation in the base class is used: A::bye()). This behavior changes if a pointer to the derived class is cast to the base class, like A* ab below. Then the base class implementation is called A::hello() is used.

Virtual methods behave differently. The derived class is called each time, e.g. both d->hello(); and cd->hello(); are resolved to D::hello().

X * x = new X(); // X = A, C
X * xy = new Y(); // Y = B, D; Y derived from X
A::hello(), A::bye() are non-virtual
C::hello(), C::bye() are virtual
B::hello() re-implemented
B::bye() not implemented, only inherited from A

x->hello();
x=a: A: hello, world!
x=b: B: non-virtual hell, oh!
x=c: C: hello!
x=d: D: virtual hell, oh!

x->bye();
x=a: A: adios amigos!
x=b: A: adios amigos!
x=c: C: adios amigos!
x=d: D: virtual hell, oh!

xy->hello();
xy=ab: A: hello, world!
xy=cd: D: virtual hell, oh!

((Y*) xy)->hello();
xy=ab: B: non-virtual hell, oh!
xy=cd: D: virtual hell, oh!

xy->bye();
xy=ab: A: adios amigos!
xy=cd: D: virtual hell, oh!

((Y*) xy)->bye();
xy=ab: A: adios amigos!
xy=cd: D: virtual hell, oh!

Edit | Attach | Watch | Print version | History: r3 < r2 < r1 | Backlinks | Raw View | WYSIWYG | More topic actions
Topic revision: r3 - 2012-12-14 - JanVeverka
 
    • Cern Search Icon Cern Search
    • TWiki Search Icon TWiki Search
    • Google Search Icon Google Search

    Main All webs login

This site is powered by the TWiki collaboration platform Powered by PerlCopyright &© 2008-2024 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
or Ideas, requests, problems regarding TWiki? use Discourse or Send feedback