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); }