ZC_C++类函数指针_模拟_Delphi类函数指针_Qt例子
qt-opensource-windows-x86-msvc2010_opengl-5.3.2.exe
ZC: “const QString” 作传入参数的时候,不太会弄... 貌似 还是在进行构建等的操作,按照暂时的水平这种情况还不太会弄... 于是 用“QString&”或“QString*”作参数
ZC: Qt调试 比较麻烦,还是使用 VS2010 来调试 看汇编的...
1、mainwindows.cpp
#include "mainwindow.h" #include "ui_mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); } MainWindow::~MainWindow() { delete ui; } #include <QDebug> #include "TClassFuncPtr.h" void MainWindow::on_pbtnTest01_clicked() { //* CTest test; void *pFunc = pointer_cast<void*>(&CTest::GetString); Tcfp_Qs_II cfp; cfp.Set(&test, pFunc); QString str = cfp.Call(1, 3); qDebug() << str; //*/ /* CTest test; QString str = test.GetString(1, 3); //*/ } void MainWindow::on_pbtnTest02_clicked() { QString str = "33"; //* CTest test; void *pFunc = pointer_cast<void*>(&CTest::GetIntFromString); Tcfp_I_CQs cfp; cfp.Set(&test, pFunc); int iRtn = cfp.Call(str); qDebug() << str; //*/ /* CTest test; int iRtn = test.GetIntFromString(str); qDebug() << iRtn; //*/ } void MainWindow::on_pbtnTest03_clicked() { QString str = "33"; //* CTest test; void *pFunc = pointer_cast<void*>(&CTest::GetIntFromString01); Tcfp_I_Qs cfp; cfp.Set(&test, pFunc); int iRtn = cfp.Call(str); qDebug() << iRtn; } void MainWindow::on_pbtnTest04_clicked() { QString str = "330"; //* CTest test; void *pFunc = pointer_cast<void*>(&CTest::GetIntFromString02); Tcfp_I_Qsp cfp; cfp.Set(&test, pFunc); int iRtn = cfp.Call(&str); qDebug() << iRtn; }
2、TClassFuncPtr.h
#ifndef TCLASSFUNCPTR_H #define TCLASSFUNCPTR_H #include <QString> // ZC: 子类 命名规则:“Tcfp_返回值类型_各个传入参数类型()” class TClassFuncPtr { public: TClassFuncPtr() { FpObj = NULL; FpFunc = NULL; } protected: void* FpObj; // ZC: 对象指针 void* FpFunc; // ZC: 类函数的 函数地址(统一使用stdcall调用约定,函数传参/调用的时候 方便一点) public: void Set(void *_pObj, void *_pFunc) { FpObj = _pObj; FpFunc = _pFunc; } bool IsValid() { return ( (FpObj != NULL) && (FpFunc != NULL) ); } }; class Tcfp_Qs_II :public TClassFuncPtr { public: QString __stdcall Call(int _i, int _j); }; class Tcfp_I_CQs :public TClassFuncPtr { public: int __stdcall Call(const QString _str); }; class Tcfp_I_Qs :public TClassFuncPtr { public: int __stdcall Call(QString &_str); }; class Tcfp_I_Qsp :public TClassFuncPtr { public: int __stdcall Call(QString *_pstr); }; // ZC: 获取 类函数指针(地址) template<typename dst_type,typename src_type> dst_type pointer_cast(src_type src) { return *static_cast<dst_type*>(static_cast<void*>(&src)); } #endif // TCLASSFUNCPTR_H class CTest { private: int Fi; public: QString __stdcall GetString(int _i, int _j); int __stdcall GetIntFromString(const QString _str); int __stdcall GetIntFromString01(QString &_str); int __stdcall GetIntFromString02(QString *_pstr); };
3、TClassFuncPtr.cpp
#include "TClassFuncPtr.h" #pragma optimize( "", off ) QString __stdcall Tcfp_Qs_II::Call(int _i, int _j) { if (IsValid()) { _asm { push _j push _i mov eax,dword ptr [ebp+0xC] push eax mov eax,[this] // ZC: 貌似和语句“mov eax,this”是一样的效果... // [eax] ==> FpObj // [eax+4] ==> FpFunc push [eax] call [eax+4] } } } int __stdcall Tcfp_I_CQs::Call(const QString _str) { if (IsValid()) { void *p = (void*)&_str; _asm { push p mov eax,[this] // ZC: 貌似和语句“mov eax,this”是一样的效果... // [eax] ==> FpObj // [eax+4] ==> FpFunc push [eax] call [eax+4] } } } int __stdcall Tcfp_I_Qs::Call(QString &_str) { if (IsValid()) { _asm { mov eax,[ebp+0xC] push eax mov eax,[this] // ZC: 貌似和语句“mov eax,this”是一样的效果... // [eax] ==> FpObj // [eax+4] ==> FpFunc push [eax] call [eax+4] } } } int __stdcall Tcfp_I_Qsp::Call(QString *_pstr) { if (IsValid()) { _asm { mov eax,[ebp+0xC] push eax mov eax,[this] // ZC: 貌似和语句“mov eax,this”是一样的效果... // [eax] ==> FpObj // [eax+4] ==> FpFunc push [eax] call [eax+4] } } } //#pragma optimize( "", on ) //#pragma optimize( "", off ) QString __stdcall CTest::GetString(int _i, int _j) { __asm { mov eax,eax mov eax,eax mov eax,eax } Fi = 10; return ( QString::number(_i)+","+QString::number(_j)+","+QString::number(Fi) ); } int __stdcall CTest::GetIntFromString(const QString _str) { return _str.toInt(); } int __stdcall CTest::GetIntFromString01(QString &_str) { return _str.toInt(); } int __stdcall CTest::GetIntFromString02(QString *_pstr) { return (*_pstr).toInt(); } #pragma optimize( "", on )
4、mainwindow.ui
4.1、
4.2、
<?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> <class>MainWindow</class> <widget class="QMainWindow" name="MainWindow"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>400</width> <height>300</height> </rect> </property> <property name="windowTitle"> <string>MainWindow</string> </property> <widget class="QWidget" name="centralWidget"> <widget class="QPushButton" name="pbtnTest01"> <property name="geometry"> <rect> <x>50</x> <y>40</y> <width>75</width> <height>23</height> </rect> </property> <property name="text"> <string>Test01</string> </property> </widget> <widget class="QPushButton" name="pbtnTest02"> <property name="geometry"> <rect> <x>50</x> <y>70</y> <width>75</width> <height>23</height> </rect> </property> <property name="text"> <string>Test02</string> </property> </widget> <widget class="QPushButton" name="pbtnTest03"> <property name="geometry"> <rect> <x>50</x> <y>100</y> <width>75</width> <height>23</height> </rect> </property> <property name="text"> <string>Test03</string> </property> </widget> <widget class="QPushButton" name="pbtnTest04"> <property name="geometry"> <rect> <x>50</x> <y>130</y> <width>75</width> <height>23</height> </rect> </property> <property name="text"> <string>Test04</string> </property> </widget> </widget> <widget class="QMenuBar" name="menuBar"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>400</width> <height>17</height> </rect> </property> </widget> <widget class="QToolBar" name="mainToolBar"> <attribute name="toolBarArea"> <enum>TopToolBarArea</enum> </attribute> <attribute name="toolBarBreak"> <bool>false</bool> </attribute> </widget> <widget class="QStatusBar" name="statusBar"/> </widget> <layoutdefault spacing="6" margin="11"/> <resources/> <connections/> </ui>
5、