使用" 参数化基类" 和" 成员函数指针" 模拟实现虚函数

// 使用" 参数化基类"" 成员函数指针" 模拟实现虚函数。

#include "stdafx.h"

 

/*

    使用 "参数化基类 " "成员函数指针 "模拟实现虚函数。

    可能大家都以为只有疯子才会这么干,好好的虚函数干吗不用,而偏要拐弯抹角地

    搞得这么复杂,但有时候这可能是最好地选择。举个例子吧,我写 Windows PE 文件

    加壳程序的时候,遇到一个问题:

    1. 我开发了一个框架,可以只用 C++ 来写 "壳程序 ",大家很难想到吧!

    2. 但不能使用一些 C++ 功能:虚函数,异常处理,还有 switch-case 语句

    3. C++ 异常处理可以不用,但是不能使用虚函数可能太过苛刻。

 

    当我看了 "generative programming"以后,觉得 "参数化继承 "

    或许可以满足这个需求,模拟实现虚函数。

    以下是使用 "参数化继承 "实现虚函数的框架,以及要注意的事项。

 

    BaseClass 显然,实际上是 "抽象基类 ",因为如果实例化

    "InstantialClass<ConcreteClass>" 时,ConcreteClass

    必须定义响应的 "虚函数 ",否则编译就报错。如果相应的

    BaseClass InstantialClass 定义正确无误(从代码可以

    看到,这很简单,但比较麻烦,必须注意一些细节)。因此

    ConcreteClass 编译期错误不会被推迟到运行时才发现,

    而使用其它方式模拟,就很难有这个保证。

 

    其实,如果了解 C++ 的底层对象模型,这些需要注意的细节

    很容易理解!

 

    //-------

    另外有一种 C 语言模拟 C++ 虚函数的方法,可以在我以前

    (2002 )一篇文章中看到。

*/

class BaseClass

{

#define DEFINE_VIRTUAL(ret , name, param_list, call_list ) /

protected :  /

    typedef ret (BaseClass ::*T## name) param_list ;   /

    T## name p ##name;     /

public :                 /

    ret name param_list /

    { return ( this->*this ->p## name)call_list ; }

 

//////

// expansion of :

/*  DEFINE_VIRTUAL(int, Func1,

        (int x1, int x2),

        (   x1,    x2)

        );

*/

protected :

    typedef int (BaseClass ::*TFunc1)( int x1 , int x2);

    TFunc1 pFunc1;

public :

    int Func1(int x1, int x2 )

    {

        return ( this->*this ->pFunc1)( x1, x2 );

    //  return (this->*pFunc1)(x1, x2); // can be simplified as this line.

    }

// end expansion

//////

 

    DEFINE_VIRTUAL( int, Func2 ,

        (int x1, int x2, int x3 ),

        (   x1 ,    x2 ,    x3 )

        );

 

protected :

    template< typename AddressType >

    AddressType convert_address(AddressType address)

    {

        // if used in shell code, this must return another valid address.

        return address;

    }

public :

    template< typename BaseFuncType , typename ConcreteFuncType>

    void assign(BaseFuncType & x, ConcreteFuncType y )

    {

    // if use C Style cast like "(BaseFunType)(y)", it is danger!!

    // any member function can be assigned to x!!

    //  x = convert_address((BaseFuncType)(y)); // danger!!

        x = convert_address(static_cast <BaseFuncType>( y));

    }

    BaseClass()

    {

        pFunc1 = 0;

        pFunc2 = 0;

    }

};

 

class ConcreteClass1

{

private :

    int x1, x2 , x3;

public :

    int Func1(int x1, int x2 )

    {

        this-> x1 = x1 ;

        this-> x2 = x2 ;

        std:: cout << "ConcreteClass1::Func1" << "/n" ;

        std:: cout << "x1=" << x1 << ", x2=" << x2 << "/n/n";

        return 0;

    }

    int Func2(int x1, int x2 , int x3)

    {

        this-> x1 = x1 ;

        this-> x2 = x2 ;

        this-> x3 = x3 ;

        std:: cout << "ConcreteClass1::Func2" << "/n" ;

        std:: cout << "x1=" << x1 << ", x2=" << x2 << ", x3=" << x3 << "/n/n";

        return 0;

    }

};

 

class ConcreteClass2

{

private :

    int x1, x2 , x3;

public :

    int Func1(int x1, int x2 )

    {

        this-> x1 = x1 ;

        this-> x2 = x2 ;

        std:: cout << "ConcreteClass2::Func1" << "/n" ;

        std:: cout << "x1=" << x1 << ", x2=" << x2 << "/n/n";

        return 0;

    }

    int Func2(int x1, int x2 , int x3)

    {

        this-> x1 = x1 ;

        this-> x2 = x2 ;

        this-> x3 = x3 ;

        std:: cout << "ConcreteClass2::Func2" << "/n" ;

        std:: cout << "x1=" << x1 << ", x2=" << x2 << ", x3=" << x3 << "/n/n";

        return 0;

    }

};

 

template <class ConcreteClass>

class InstantialClass :

    // "BaseClass" must be first base class, otherwise,

    // function pointer convert in "BaseClass::assign()" may be not valid!

    public BaseClass, // interface inherit, multi inherit is not allowed!!

    protected ConcreteClass // implementation inherit, multi inherit is allowed

{

    // it is a guide line that do not hold any data member in this class!!

    //

    // if 'BaseClass' is not the first base class for 'this' class,

    // and data member is defined here,

    // and these data member will be modified,

    // it will error at runtime!

    // you can reverse the inherit order of

    // BaseClass and ConcreteClass, and try!!

    //

    int x1, x2 , x3;

public :

    // must delegate these member functions...

    int Func1(int x1, int x2 ) { return ConcreteClass::Func1 (x1, x2); }

    int Func2(int x1, int x2 , int x3)

    {

        this-> x1 = x1 ;

        this-> x2 = x2 ;

        this-> x3 = x3 ;

        return ConcreteClass::Func2 (x1, x2, x3 );

    }

 

    InstantialClass()

    {

    // must assign these member function pointers...

    //  BaseClass::pFunc1 = (TFunc1)(Func1);

        assign( pFunc1, Func1 );

        assign( pFunc2, Func2 );

 

    // if use C Style cast in assign, follow line can be compiled,

    // but will error at runtime, because pointer to ConcreteClass

    // is different from to 'this'!!

    // pointer to 'BaseClass' is equal to 'this'..

    // so, do not write such code,

    // must delegate 'ConcreteClass::Func2' to 'this->Func2'.

    // assign(pFunc2, ConcreteClass::Func2);

    }

};

 

int _tmain( int argc , _TCHAR* argv[])

{

    BaseClass* p1 = new InstantialClass< ConcreteClass1>();

    BaseClass* p2 = new InstantialClass< ConcreteClass2>();

 

    p1-> Func1(1111 , 2222);

    p2-> Func1(1111 , 2222);

    p1-> Func2(1111 , 2222, 3333);

    p2-> Func2(1111 , 2222, 3333);

 

    p1-> Func1(1111 , 2222);

    p2-> Func1(1111 , 2222);

    p1-> Func2(1111 , 2222, 3333);

    p2-> Func2(1111 , 2222, 3333);

 

    delete p2;

    delete p1;

 

    return 0;

}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值