/**/
/*
Runtime Concept 的模拟(3)
虚函数转发,太间接了。
改之。
基本原理:
1. 自己实现vtable。
2. 同时转发<T>的new和delete,实现存值。
缺陷:
1. 成员函数的调用方法不知道是不是符合标准,不过估计移植性没什么问题。
2. static应该改为多线程安全的Singleton。
3. 太复杂。
另:
1. VC的非虚成员函数指针居然可以指向虚函数并正常调用,诡异。
2. 引用方式的concept只要去掉new和delete的调用即可。
*/
#include < stdio.h >
#include < vector >
#include < algorithm >
#include < string >
typedef FILE * monitor;
struct Rectangle
... {
void draw(monitor device) const
...{
fprintf(device, "Rectangle.draw ");
}
void draw() const
...{
printf("Rectangle.draw ? ");
}
} ;
struct Ellipse
... {
virtual void draw(monitor device) const
...{
fprintf(device, "Ellipse.draw virtual ");
}
} ;
struct Triangle
... {
int draw(monitor device, int another_arg) const
...{
fprintf(device, "Triangle.draw? ");
return 0;
}
} ;
void drawShape( const Rectangle & refShape, monitor device)
... {
refShape.draw(device);
}
void drawShape( const Ellipse & refShape, monitor device)
... {
refShape.draw(device);
}
void drawShape( const Triangle & refShape, monitor device)
... {
refShape.draw(device, 0);
}
// concept
class Shape
... {
private:
typedef Shape object;
template <class T>
struct ctable
...{
typedef T* (T::*tcloneT)() const;
typedef void (T::*tdeleteT)();
typedef void (T::*tdraw)(monitor device) const;
typedef void (*tglobal_drawShape)(const T &refShape, monitor device);
tcloneT pcloneT;
tdeleteT pdeleteT;
tdraw pdraw;
tglobal_drawShape pglobal_drawShape;
ctable() :
pcloneT(reinterpret_cast<tcloneT>(&ctable::cloneT)),
pdeleteT(reinterpret_cast<tdeleteT>(&ctable::deleteT)),
pdraw(&T::draw),
pglobal_drawShape(&::drawShape) ...{}
static ctable* vtable()
...{
static ctable static_table;
return &static_table;
}
T *cloneT() const
...{
return new T(*reinterpret_cast<const T*>(this));
}
void deleteT()
...{
delete reinterpret_cast<T*>(this);
}
};
object *pointer;
ctable<object> *ptable;
object *cloneT() const
...{
return (pointer->*ptable->pcloneT)();
}
void deleteT()
...{
(pointer->*ptable->pdeleteT)();
}
public:
void draw(monitor device) const
...{
(pointer->*ptable->pdraw)(device);
}
static void drawShape(const Shape &refShape, monitor device)
...{
(*refShape.ptable->pglobal_drawShape)(*refShape.pointer, device);
}
template <class T>
Shape(const T& t) :
pointer(reinterpret_cast<object *>(new T(t))),
ptable(reinterpret_cast<ctable<object>*>(ctable<T>::vtable())) ...{}
Shape(const Shape& rhs) : pointer(rhs.cloneT()), ptable(rhs.ptable) ...{}
Shape& operator = (const Shape& rhs)
...{
Shape tShape(rhs);
swap(tShape);
return *this;
}
void swap(Shape& rhs)
...{
std::swap(pointer, rhs.pointer);
std::swap(ptable, rhs.ptable);
}
~Shape()
...{
deleteT();
}
} ;
void DrawShapes(monitor device, std::vector < Shape > const & g)
... {
std::vector<Shape>::const_iterator b(g.begin()), e(g.end());
for(; b != e; ++b)
...{
b->draw(device);
Shape::drawShape(*b, device);
}
}
int main( int argc, char * argv[])
... {
std::vector<Shape> vg;
vg.push_back(Rectangle());
vg.push_back(Ellipse());
vg.push_back(vg[0]);
vg.push_back(vg[2]);
vg[3] = vg[1];
//vg.push_back(Triangle()); //错误,不符合Shape concept
//vg.push_back(std::string("xxx")); //错误,不符合Shape concept
DrawShapes(stdout, vg);
return 0;
}
Runtime Concept 的模拟(3)
虚函数转发,太间接了。
改之。
基本原理:
1. 自己实现vtable。
2. 同时转发<T>的new和delete,实现存值。
缺陷:
1. 成员函数的调用方法不知道是不是符合标准,不过估计移植性没什么问题。
2. static应该改为多线程安全的Singleton。
3. 太复杂。
另:
1. VC的非虚成员函数指针居然可以指向虚函数并正常调用,诡异。
2. 引用方式的concept只要去掉new和delete的调用即可。
*/
#include < stdio.h >
#include < vector >
#include < algorithm >
#include < string >
typedef FILE * monitor;
struct Rectangle
... {
void draw(monitor device) const
...{
fprintf(device, "Rectangle.draw ");
}
void draw() const
...{
printf("Rectangle.draw ? ");
}
} ;
struct Ellipse
... {
virtual void draw(monitor device) const
...{
fprintf(device, "Ellipse.draw virtual ");
}
} ;
struct Triangle
... {
int draw(monitor device, int another_arg) const
...{
fprintf(device, "Triangle.draw? ");
return 0;
}
} ;
void drawShape( const Rectangle & refShape, monitor device)
... {
refShape.draw(device);
}
void drawShape( const Ellipse & refShape, monitor device)
... {
refShape.draw(device);
}
void drawShape( const Triangle & refShape, monitor device)
... {
refShape.draw(device, 0);
}
// concept
class Shape
... {
private:
typedef Shape object;
template <class T>
struct ctable
...{
typedef T* (T::*tcloneT)() const;
typedef void (T::*tdeleteT)();
typedef void (T::*tdraw)(monitor device) const;
typedef void (*tglobal_drawShape)(const T &refShape, monitor device);
tcloneT pcloneT;
tdeleteT pdeleteT;
tdraw pdraw;
tglobal_drawShape pglobal_drawShape;
ctable() :
pcloneT(reinterpret_cast<tcloneT>(&ctable::cloneT)),
pdeleteT(reinterpret_cast<tdeleteT>(&ctable::deleteT)),
pdraw(&T::draw),
pglobal_drawShape(&::drawShape) ...{}
static ctable* vtable()
...{
static ctable static_table;
return &static_table;
}
T *cloneT() const
...{
return new T(*reinterpret_cast<const T*>(this));
}
void deleteT()
...{
delete reinterpret_cast<T*>(this);
}
};
object *pointer;
ctable<object> *ptable;
object *cloneT() const
...{
return (pointer->*ptable->pcloneT)();
}
void deleteT()
...{
(pointer->*ptable->pdeleteT)();
}
public:
void draw(monitor device) const
...{
(pointer->*ptable->pdraw)(device);
}
static void drawShape(const Shape &refShape, monitor device)
...{
(*refShape.ptable->pglobal_drawShape)(*refShape.pointer, device);
}
template <class T>
Shape(const T& t) :
pointer(reinterpret_cast<object *>(new T(t))),
ptable(reinterpret_cast<ctable<object>*>(ctable<T>::vtable())) ...{}
Shape(const Shape& rhs) : pointer(rhs.cloneT()), ptable(rhs.ptable) ...{}
Shape& operator = (const Shape& rhs)
...{
Shape tShape(rhs);
swap(tShape);
return *this;
}
void swap(Shape& rhs)
...{
std::swap(pointer, rhs.pointer);
std::swap(ptable, rhs.ptable);
}
~Shape()
...{
deleteT();
}
} ;
void DrawShapes(monitor device, std::vector < Shape > const & g)
... {
std::vector<Shape>::const_iterator b(g.begin()), e(g.end());
for(; b != e; ++b)
...{
b->draw(device);
Shape::drawShape(*b, device);
}
}
int main( int argc, char * argv[])
... {
std::vector<Shape> vg;
vg.push_back(Rectangle());
vg.push_back(Ellipse());
vg.push_back(vg[0]);
vg.push_back(vg[2]);
vg[3] = vg[1];
//vg.push_back(Triangle()); //错误,不符合Shape concept
//vg.push_back(std::string("xxx")); //错误,不符合Shape concept
DrawShapes(stdout, vg);
return 0;
}