使用" 参数化基类" 和" 成员函数指针" 模拟实现虚函数
// 使用" 参数化基类" 和" 成员函数指针" 模拟实现虚函数。
#include "stdafx.h"
/*
使用 "参数化基类 "和 "成员函数指针 "模拟实现虚函数。
可能大家都以为只有疯子才会这么干,好好的虚函数干吗不用
搞得这么复杂,但有时候这可能是最好地选择。举个例子吧,我写 Windows PE 文件
加壳程序的时候,遇到一个问题:
1. 我开发了一个框架,可以只用 C++ 来写 "壳程序 ",大家很难想到吧!
2. 但不能使用一些 C++ 功能:虚函数,异常处理,还有 switch-case 语句
3. C++ 异常处理可以不用,但是不能使用虚函数可能太过苛刻。
当我看了 "generative programming"以后,觉得 "参数化继承 "
或许可以满足这个需求,模拟实现虚函数。
以下是使用 "参数化继承 "实现虚函数的框架,以及要注意的事项。
BaseClass 显然,实际上是 "抽象基类 ",因为如果实例化
"InstantialClass<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)
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;
}