• 使用C/C++给静态类型数据添加运算符重载功能


    1 说明

        要演示本文的例子,你必须下载Lu32脚本系统。本文的例子需要lu32.dll、lu32.lib、C格式的头文件lu32.h,相信你会找到并正确使用这几个文件。

        用C/C++编译器创建一个控制台应用程序,复制本文的例子代码直接编译运行即可。

    2 关于运算符重载

        在本教程系列的开始,介绍了Lu脚本的基本数据结构(详细参考Lu编程指南),即:

    1. struct LuData{    //Lu基本数据结构。  
    2.     luIFOR x;     //luIFOR被定义为64位整数__int64,用于存放数据。对于动态数据类型,对象指针约定保存在x的前4个字节中。  
    3.     luIFOR y;     //存放数据。  
    4.     luIFOR z;     //存放数据。  
    5.     luKEY  VType; //luKEY被定义为32位整数__int32。扩展数据类型,决定重载函数,从而决定了对数据的操作方式。  
    6.     luKEY  BType; //基本数据类型,决定了Lu数据的结构。  
    7. };  

        基本数据类型BType决定了实际的数据结构,而扩展数据类型VType决定了重载函数。若要对某数据类型VType进行运算符重载,需要用函数LockKeyVType加锁,该函数定义如下:

    int _stdcall LockKey(luKEY VType,void (_stdcall *DeleteKey)(void *),luOperator OpLock);

        VType:被锁定的键的类型。VType>luPubKey_User(公有键、普通键)或者 VType<luPriKey_User(私有键)
        
    DeleteKey:删除键值的函数指针,用于标识要加锁的键。该函数由用户定义,但由Lu调用。若DeleteKey=NULL,表示解锁指定的键。
        
    OpLockluOperator类型的函数指针,用于对象(用指针标识)的运算符重载,该参数不可为NULL。解锁和加锁所用的OpLock函数必须相同。参考[注1]

        如果加锁或解锁成功,该函数返回0,否则返回非0值。

        [注1]:运算符重载函数luOperator函数格式如下(与Lu二级函数相比,仅多了一个参数theOperator):

    1. //m指出数组Para的参数个数(也即操作数的个数,0表示1个,1表示2个,以此类推)。  
    2. //hFor为调用该函数的表达式句柄(与二级函数中的表达式句柄相同)。  
    3. //theOperator指出运算符的类型或操作类型:+、-、*、/、^、... ...。  
    4. LuData (_stdcall *luOperator)(luINT m,LuData *Para,void *hFor,int theOperator);  
    5.   
    6. LuData _stdcall OpLock(luINT m,LuData *Para,void *hFor,int theOperator)  
    7. {  
    8.     //... ...  
    9.     switch(theOperator)  
    10.     {  
    11.     case 0:    //重载运算符+  
    12.         //... ...  
    13.     case 1:    //重载运算符-  
    14.         //... ...  
    15.     case 2:    //重载运算符*  
    16.         //... ...  
    17.     case 3:    //重载运算符%  
    18.         //... ...  
    19.     case 4:    //重载运算符/  
    20.         //... ...  
    21.     ... ...  
    22.     }  
    23. }  


        如果不打算给加锁的键提供运算符或函数重载功能,须使用函数SetRunErr向Lu报告运行错误。

        本文讨论使用C/C++给静态类型数据添加运算符重载功能。本文的例子是实现C/C++中的单字节字符类型 char(基本类型为 luStaData_int64,扩展类型为 key_char),但仅定义了部分运算。

    3 代码

    1. #include <stdio.h>  
    2. #include "lu32.h"  
    3.   
    4. #pragma comment( lib, "lu32.lib" )  
    5.   
    6. luKEY key_char = luPoiKey_User-20;  //标识char的私有键,将对其加锁  
    7.   
    8. void _stdcall Del_char(void *me)    //销毁char的函数,但什么也不做,只为了配合运算符重载,加锁键使用  
    9. {  
    10. }  
    11.   
    12. LuData _stdcall OpLock_char(luINT m,LuData *Para,void *hFor,int theOperator)    //char的运算符重载函数  
    13. {  重生之大文豪www.dwhao.com
    14.     LuData a;  
    15.   
    16.     switch(theOperator)  
    17.     {  
    18.     case 0:     //重载运算符+  
    19.         if(Para[0].BType!=luStaData_int64 || Para[1].BType!=luStaData_int64) goto err;  //要求基本类型为整数  
    20.         a.BType=key_char; a.VType=key_char; a.x=(char)((char)(Para[0].x)+(char)(Para[1].x));  
    21.         break;  
    22.     case 1:     //重载运算符-  
    23.         if(Para[0].BType!=luStaData_int64 || Para[1].BType!=luStaData_int64) goto err;  //要求基本类型为整数  
    24.         a.BType=key_char; a.VType=key_char; a.x=(char)((char)(Para[0].x)-(char)(Para[1].x));  
    25.         break;  
    26.     case 2:     //重载运算符*  
    27.         if(Para[0].BType!=luStaData_int64 || Para[1].BType!=luStaData_int64) goto err;  //要求基本类型为整数  
    28.         a.BType=key_char; a.VType=key_char; a.x=(char)((char)(Para[0].x)*(char)(Para[1].x));  
    29.         break;  
    30.     case 3:     //重载运算符%  
    31.         if(Para[0].BType!=luStaData_int64 || Para[1].BType!=luStaData_int64) goto err;  //要求基本类型为整数  
    32.         a.BType=key_char; a.VType=key_char; a.x=(char)((char)(Para[0].x)%(char)(Para[1].x));  
    33.         break;  
    34.     case 4:     //重载运算符/  
    35.         if(Para[0].BType!=luStaData_int64 || Para[1].BType!=luStaData_int64) goto err;  //要求基本类型为整数  
    36.         a.BType=key_char; a.VType=key_char; a.x=(char)((char)(Para[0].x)/(char)(Para[1].x));  
    37.         break;  
    38.     default:  
    39.         a.BType=luStaData_nil; a.VType=luStaData_nil; a.x=0;    //没有重载该运算符或者函数,返回nil  
    40.         SetRunErr(1,L"char 无法识别的运算符!",theOperator,0,hFor);  
    41.     }  
    42.     return a;  
    43. err:  
    44.     a.BType=luStaData_nil; a.VType=luStaData_nil; a.x=0;        //参数不符合要求,返回nil  
    45.     SetRunErr(1,L"char 参数无法识别!",theOperator,0,hFor);  
    46.     return a;  
    47. }  
    48.   
    49. //Lu脚本可调用的二级函数定义  
    50. LuData _stdcall lu_int2char(luINT mm,LuData *xx,void *vFor)     //将一个整数转换为char  
    51. {  
    52.     static wchar_t ErrName[]=L"int2char";  
    53.     LuData a;  
    54.   
    55.     if(xx->BType==luStaData_int64)  
    56.     {  
    57.         a.BType = luStaData_int64; a.VType = key_char;  //设置数据的基本类型和扩展类型  
    58.         a.x = (char)xx->x;  
    59.     }  
    60.     else    //出错时向Lu系统报告运行错误  
    61.     {  
    62.         a.BType=luStaData_nil; a.VType=luStaData_nil; a.x=0;  
    63.         SetRunErr(1,ErrName,1,0,vFor);  
    64.     }  
    65.     return a;  
    66. }  
    67.   
    68. void main(void)  
    69. {  
    70.     void *hFor;     //存放表达式句柄,即脚本函数句柄  
    71.     luINT nPara;        //存放表达式的自变量个数  
    72.     LuData *pPara;      //存放输入自变量的数组指针  
    73.     LuData Val;     //存放表达式的值  
    74.     luINT ErrBegin,ErrEnd;  //表达式编译出错的初始位置和结束位置  
    75.     int ErrCode;        //错误代码  
    76.     wchar_t ForStr[]=L"int2char(800) % int2char(500)";  //字符串表达式  
    77.   
    78.     if(!InitLu()) return;   //初始化Lu  
    79.   
    80.     SetFunction(L"int2char",lu_int2char,0); //设置二级函数  
    81.   
    82.     LockKey(key_char,Del_char,OpLock_char); //在Lu键树中加锁键,只能存储char类型,但实际上什么也不存储,只为了配合运算符重载  
    83.   
    84.     ErrCode=LuCom(ForStr,0,0,0,&hFor,&nPara,&pPara,&ErrBegin,&ErrEnd);  //编译表达式  
    85.     if(ErrCode)  
    86.     {  
    87.         printf("表达式有错误!错误代码: %d  ",ErrCode);  
    88.     }  
    89.     else  
    90.     {  
    91.         Val=LuCal(hFor,pPara);  //计算表达式的值,hFor即编译得到的表达式句柄  
    92.         if(Val.VType==key_char) printf("Lu表达式的值: %I64d  ",Val.x);  
    93.     }  
    94.     printf("C 表达式的值: %d  ",((char)800) % ((char)500));  
    95.   
    96.     LockKey(key_char,NULL,OpLock_char);     //在Lu键树中解锁键  
    97.   
    98.     FreeLu();           //释放Lu  
    99. }  


    运行结果:

    Lu表达式的值: 8
    C 表达式的值: 8

    4 函数说明

        本例用到了Lu的6个输出函数:初始化Lu的函数InitLu,释放Lu的函数FreeLu,编译表达式的函数LuCom、计算表达式的函数LuCal、加锁键函数LockKey、注册C/C++函数的函数SetFunction。从这里查看这些函数的说明:Lu编程指南

    5 难点分析

        在给静态类型数据添加运算符重载功能时,需要:(1)用LockKey加锁一个键(本例为key_char),但不需要向Lu系统注册任何键值;(2)删除键值的函数(本例为Del_char)定义为空函数;(3)定义运算符重载函数(本例为OpLock_char)。

        根据函数OpLock_char中定义的运算规则可知,代码中的字符串表达式定义为 "int2char(800) % 500" 或者 "800 % int2char(500)"有相同的运算结果,很明显,本例较简单,没有实现不同数据类型的自动转换。

    6 其他

        你可能注意到了,我的联系方式就在下面,如有不明之处或有什么建议,可随时与我进行联系。

  • 相关阅读:
    俄罗斯的 HTTPS 证书问题
    11. 第十篇 网络组件flanneld安装及使用
    8.第七篇 验证kubeapiserver及kubeconfig配置详解
    4.第三篇 PKI基础概念、cfssl工具介绍及kubernetes中证书
    不要舔 Switch 游戏卡,单性生殖,永久夏令时
    catalina.out日志割接
    15. 第十四篇 安装CoreDNS
    6.第五篇 安装keepalived与Nginx
    5.第四篇 Etcd存储组件高可用部署
    DirectPV文章内容有待进一步实践完善
  • 原文地址:https://www.cnblogs.com/jiangye/p/3508878.html
Copyright © 2020-2023  润新知