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、

 

posted @ 2017-01-12 08:52  CppSkill  阅读(287)  评论(0编辑  收藏  举报