成员函数指针的应用 之 仿写OC里面UIButton的回调机制(三)

//
//  main.cpp
//  Basic
//
//  Created by 06 on 15/1/9.
//  Copyright (c) 2015年 黄永锐. All rights reserved.
//

#include <iostream>
using namespace std;
class UIButton;

//
struct NSObject{//负责内存管理的类
    bool init(){

        return true;
    }
};

//英雄类
struct Hero:public NSObject{
    void move(UIButton* button){
        cout << "英雄移动了" << endl;
    }
};

//成员函数指针的别名
typedef void (NSObject::*FUNC)(UIButton*);

#pragma 结构体中的变量  不写权限   默认都是公开的。  类中,不写权限,默认都是私有的。

//C++的继承是单冒号: public是公开继承
struct UIButton :public NSObject{

private:  //成员变量  一般都是私有的,然后给它提供公开的set  get 接口方法
    int _tag;
    NSObject *_target;//这只是指针 还应该要创建他,在哪里创建?初始化方法里面??不行,因为如果你想要2个英雄的话,那岂不是要创建2个按钮??应该在创建按钮的时候传进去
    FUNC _func;

public:
    //对于OC来说  创建对象都有一个类方法+
#pragma 动态传进对象和方法  只要满足这种格式的回调方法的地址都可以传
    static UIButton* buttonWithTarget(NSObject *target,FUNC func){

        //创建对象
        //第一步是开辟空间
        UIButton *m_button = new UIButton;//这里并不像OC的alloc 创建出来计数器就+1,在C++中没有引用计数器的概念所以没有加一减一。。。开辟空间就new,释放就delete

        //第二步是初始化
        if (m_button->initWithTarget(target,func)) {//指针访问方法用箭头
            //如果是OC里面的话 这里还会调用 autorelease()

            //第三部返回对象的指针
            return m_button;
        }

        //如果初始化失败
        //销毁空间
        delete m_button;
        //防止野指针
        m_button = nullptr;

        return NULL;

    }

    // 返回布尔值判断是否初始化成功
    bool initWithTarget(NSObject *target,FUNC func) {
#pragma 注意原理   子类初始化一定先要调用父类的初始化方法(因为父类的初始化里面可能给某个变量赋值了,如果你没有调用父类的初始化,那么你继承下来的就没有值)
        if (!NSObject::init()) {
            return false;//父类初始化失败
        }

        //初始化子类自己的东西
        _target = target;
        _func = func;//
        return true;

    }

    //成员变量的set  get方法
    int getTag(){
        return _tag;
    }
    void setTag(int tag){
        //如果在OC里面有这么一个方法self.tag = tag;会有问题吗?有!死循环!
        _tag = tag;
    }

    //模拟点击button的时候
    void touch(){

        cout << "Button被点中" << endl;
    }//我现在希望点中的时候英雄移动(不是打印一句话,而是英雄对象调用他自身的移动方法)

    void touch1(){
#pragma 这个函数指针需要一个参数  参数类型是UIButton 把自身带出去到回调函数里面
        (_target ->* _func)(this);

        void func(UIButton*);
    }

};

//
struct Plane : public NSObject{

    void fly(UIButton* button){
        cout << "飞机??正在飞行" << endl;
    }
};

//主函数
int main(){

#pragma 问题
    //但是我现在想把button放在飞机的身上,点击让飞机移动   那么我岂不是要把源文件英雄改成飞机??
    //也就是说我想button通用,怎么办?button代表的对象只能动态获取,执行的方法也需要动态获取 _hero -> move();

    //应该把英雄对象 提出来作为参数,但是参数类型不能固定为英雄,而是NSObject类型,无论是飞机坦克大炮  都可以传进来

    //创建英雄
    Hero* hero = new Hero;
    //创建button
    UIButton *button = UIButton::buttonWithTarget(hero, (FUNC)&Hero::move);//强制转换
    button->touch1();

    //创建飞机对象
    Plane *plane = new Plane;
    UIButton *button2 = UIButton::buttonWithTarget(plane, (FUNC)&Plane::fly);
    button2 -> touch1();

    //方法选择器  实际上是宏

#define selector(SET) (FUNC)&SET  //SET宏参数的
    //创建button
    UIButton *button3 = UIButton::buttonWithTarget(hero, selector(Hero::move));
    button3->touch1();

    return 0;
}
时间: 2024-11-04 06:29:31

成员函数指针的应用 之 仿写OC里面UIButton的回调机制(三)的相关文章

C++成员函数指针错误用法警示(成员函数指针与高性能的C++委托,三篇),附好多评论

今天做一个成绩管理系统的并发引擎,用Qt做的,仿照QtConcurrent搞了个模板基类.这里为了隐藏细节,隔离变化,把并发的东西全部包含在模板基类中.子类只需注册需要并发执行的入口函数即可在单独线程中执行.最终目标是,继承的业务逻辑类外部调用时有两个接口可选,调用syncRun同步执行:调用由引擎自动生成的asyncRun就异步执行.最终自动生成asyncRun的模板基类没能实现,主要原因是mingw对this处理的太有问题了!!原本以为编译器问题,后来才知道成员函数指针和this指针如此特殊

类的成员函数指针(比較深入)

From:http://blog.csdn.net/hairetz/archive/2009/05/06/4153252.aspx 个人感觉对于类的成员函数指针这块解说的比較深入具体 推荐阅读 ///////////////////////////////////////////////// 先看这样一段代码 class test {    public:       test(int i){ m_i=i;}       test(){} void hello()       {        

成员函数指针与高性能的C++委托

成员函数指针与高性能的C++委托(上篇) 撰文:Don Clugston 引子 标准C++中没有真正的面向对象的函数指针.这一点对C++来说是不幸的,因为面向对象的指针(也叫做"闭包(closure)"或"委托 (delegate)")在一些语言中已经证明了它宝贵的价值.在Delphi (Object Pascal)中,面向对象的函数指针是Borland可视化组建库(VCL,Visual Component Library)的基础.而在目前,C#使"委托&

函数指针与类成员函数指针

1,函数指针函数指针,顾名思义就是函数的指针,而指针其实就是地址,那么函数指针就是存储函数的地址,可是实际大部分时间里,我们写程序时是根本不会去考虑函数地址在哪里.我们只需要知道函数原型和函数声明就可以.但是想象一下,我们总是以为函数就应该接收参数,那么函数本身是否可以作为函数的参数呢?我做了下面的一个实验 #include<iostream>#include<stdio.h>#include<cstring>using namespace std;typedef in

成员函数指针和指向静态成员函数的指针

#include <iostream> using namespace std; class Student{ public:     Student(const string& name):m_name(name){}     void who(void){         cout << m_name << endl;     }     string m_name;     static int s_add(int a,int b){         re

C++ 指向成员函数指针问题

成员函数指针与常规指针不同,一个指向成员变量的指针并不指向一个内存位置.通常最清晰的做法是将指向数据成员的指针看作为一个偏移量. class ru_m { public: typedef int (ru_m::*p)(); p get_m(); int show(); }; int ru_m::show(){ return 10000; } ru_m::p ru_m::get_m(){ ru_m::p vc; //错误,当为对象时,对象指向的地址为相对地址,非内存地址 //所以,ru_m->sh

为什么 C++ 中成员函数指针是 16 字节?

当我们讨论指针时,通常假设它是一种可以用 void * 指针来表示的东西,在 x86_64 平台下是 8 个字节大小.例如,下面是来自 维基百科中关于 x86_64 的文章 的摘录: Pushes and pops on the stack are always in 8-byte strides, and pointers are 8 bytes wide. 从 CPU 的角度来看,指针无非就是内存的地址,所有的内存地址在 x86_64 平台下都是由 64 位来表示,所以假设它是 8 个字节是

C++成员函数指针的应用

 C++中,成员指针是最为复杂的语法结构.但在事件驱动和多线程应用中被广泛用于调用回叫函数.在多线程应用中,每个线程都通过指向成员函数的指针来调用该函数.在这样的应用中,如果不用成员指针,编程是非常困难的.  刚遇到这种语法时也许会让你止步不前.但你会发现,使用恰当的类型定义之后,复杂的语法是可以简化的.本文引导你了解成员函数指针的声明,赋值和调用回叫函数.  成员函数指针的声明  一个成员函数指针包括成员函数的返回类型,后随::操作符类名,指针名和函数的参数.初看上去,语法有点复杂.其实可以把

一个完整的使用成员函数指针的例子

Screen.h #ifndef SCREEN_H #define SCREEN_H #include <string> class Screen { public: typedef std::string::size_type pos; // Action is a type that can point to a member function of Screen // that returns a reference to a Screen and takes no arguments