Where are the virtual functions? Where is the hierarchy?

VC++7.1とGCC3.3.3で確認.

#include <iostream>
#include <string>

// shape抽象基底クラス.というかinterface.これのオブジェクトは
// それ自身参照として振舞う.
class shape
{
public:
  template<class T>
  shape(T &x)
    : this_(&x)
    , vptr_(&vtbl_initializer<T>::vtbl_)
  { }

  void draw() const
  { vptr_->draw(this_); }

  std::string who_are_you() const
  { return vptr_->who_are_you(this_); }

  void set_x(int x)
  { vptr_->set_x(this_, x); }

  void set_y(int y)
  { vptr_->set_y(this_, y); }

  int get_x() const
  { return vptr_->get_x(this_); }

  int get_y() const
  { return vptr_->get_y(this_); }

private:
  // 手製vtbl
  struct table
  {
    void (*draw)(void const *);
    std::string (*who_are_you)(void const *);
    void (*set_x)(void *, int);
    void (*set_y)(void *, int);
    int (*get_x)(void const *);
    int (*get_y)(void const *);
  };

  // vtbl initializer
  template<class T>
  struct vtbl_initializer
  {
    static table vtbl_;

    static void draw(void const *this_)
    { static_cast<T const *>(this_)->draw(); }

    static std::string who_are_you(void const *this_)
    { return static_cast<T const *>(this_)->who_are_you(); }

    static void set_x(void *this_, int x)
    { return static_cast<T *>(this_)->set_x(x); }

    static void set_y(void *this_, int y)
    { return static_cast<T *>(this_)->set_y(y); }

    static int get_x(void const *this_)
    { return static_cast<T const *>(this_)->get_x(); }

    static int get_y(void const *this_)
    { return static_cast<T const *>(this_)->get_y(); }
  };

  void *this_;
  table *vptr_;
};

// initializer template for vtbl
template<class T>
shape::table shape::vtbl_initializer<T>::vtbl_ = 
{
  &shape::vtbl_initializer<T>::draw
, &shape::vtbl_initializer<T>::who_are_you
, &shape::vtbl_initializer<T>::set_x
, &shape::vtbl_initializer<T>::set_y
, &shape::vtbl_initializer<T>::get_x
, &shape::vtbl_initializer<T>::get_y
};



// shapeの派生クラス.ただしshapeを継承していない.・・・なんじゃそりゃ.
class triangle
{
public:
  triangle(int x = 0, int y = 0)
    : x_(x)
    , y_(y)
  { }

  void draw() const
  { std::cout << "triangle::draw" << std::endl; }

  std::string who_are_you() const
  { return "I'm a triangle."; }

  void set_x(int x)
  { x_ = x; }

  void set_y(int y)
  { y_ = y; }

  int get_x() const
  { return x_; }

  int get_y() const
  { return y_; }

private:
  int x_;
  int y_;
};



// triangleと同様.
class rectangle
{
public:
  rectangle(int x = 0, int y = 0)
    : x_(x)
    , y_(y)
  { }

  void draw() const
  { std::cout << "rectangle::draw" << std::endl; }

  std::string who_are_you() const
  { return "I'm a rectangle."; }

  void set_x(int x)
  { x_ = x; }

  void set_y(int y)
  { y_ = y; }

  int get_x() const
  { return x_; }

  int get_y() const
  { return y_; }

private:
  int x_;
  int y_;
};



void f(shape s)
{
  using namespace std;

  s.draw();
  cout << s.who_are_you() << endl;
  cout << '(' << s.get_x() << ',' << s.get_y() << ')' << endl;
  s.set_x(2);
  s.set_y(3);
  cout << '(' << s.get_x() << ',' << s.get_y() << ')' << endl;
}

int main()
{
  triangle t;
  rectangle r;
  f(t);
  f(r);
}

コンストラクタテンプレートとinitializer templateを組み合わせて手製vtblを初期化する技法はさすがに感動したにょ・・・.トランポリンに近い技法だにゃ.トランポリンよりも理解しやすいけど.