Runtime Concept 的模拟(3)

/*
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;
}

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值