成员函数指针的应用 之 仿写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;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值