C#委托、C++委托实现、C回调函数

本文介绍了C#中的委托概念,它允许将方法作为参数传递,提高代码灵活性和可扩展性。委托可用于实现事件处理和回调,例如声明、实例化及多播委托的使用。此外,还讨论了匿名方法和C++中的类似机制。最后,提到了C语言的回调函数及其简化声明的typedef应用。
摘要由CSDN通过智能技术生成

C#委托

C# 中的委托(Delegate)定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递,这种将方法动态地赋给参数的做法,可以避免在程序中大量使用if-else(switch)语句,同时使得程序具有更好的可扩展性。委托特别用于实现事件和回调方法。所有的委托都派生自 System.Delegate 类。

声明委托

        委托声明决定了可由该委托引用的方法。委托可指向一个与其具有相同标签的方法。

        语法

修饰符 delegate 返回值类型 委托名 ( 参数列表 );

delegate void IntMethodInvoker(intx);

 定义了一个委托叫做 IntMethodInvoker ,这个委托可以指向带有一个int类型的参数,并且返回值是void的一个方法。

        定义一个委托要定义方法的参数和返回值,使用delegate定义delegate void FirstInvoke(int x);

实例化委托

        在定义好委托后就可以实例化委托,命名方法委托在实例化委托时必须带入方法的具体名称或者是null。

委托名  委托对象名 = new 委托名 ( 方法名 );

 委托数组

 委托名[] 委托对象名 = {委托的方法1,......}; 

委托做完函数的参数 

访问类型 static 返回类型 方法名(委托类型 委托参数,参数.....)  

多播委托

        委托可以包含多个方法,这种委托叫做多播委托。使用多播委托就可以按照顺序调用多个方法,多播委托只能得到调用的最后一个方法的结果,一般我们把多播委托的返回类型声明为void。

Action action1 = Test1;

action2 += Test2;

action2 -= Test1

//获取委托列表

Delegate[] delegate = action1.GetInvocationList();

匿名方法

        不用去定义一个方法,而是在后面直接使用匿名的方法。相当于直接把要引用的方法直接写在了后面,优点是减少了要编写的代码,减少代码的复杂性。

 Func<T> 委托对象名 = delegate(方法参数){

        方法体

};

事件

        事件(Event)是类或者对象向其他类或对象通知发送的事情的一种特殊签名的委托

        事件的声明

public event 委托类型 事件名;

事件使用event关键词来声明,他的返回值是一个委托类型

        通常事件的命名,以名字+Event 作为他的名称,在编码中尽量使用规范命名,增加代码可读性。

 示例代码:

using System;

delegate int NumberChanger(int n);
namespace DelegateAppl
{
   class TestDelegate
   {
      static int num = 10;
      public static int AddNum(int p)
      {
         num += p;
         return num;
      }

      public static int MultNum(int q)
      {
         num *= q;
         return num;
      }
      public static int getNum()
      {
         return num;
      }

      static void Main(string[] args)
      {
         // 创建委托实例
         NumberChanger nc1 = new NumberChanger(AddNum);
         NumberChanger nc2 = new NumberChanger(MultNum);
         // 使用委托对象调用方法
         nc1(25);
         Console.WriteLine("Value of Num: {0}", getNum());
         nc2(5);
         Console.WriteLine("Value of Num: {0}", getNum());
         Console.ReadKey();
      }
   }
}

C++ 委托实现

委托实际上就是将任意个同类型的函数交给一个对象(委托对象)来实现,可以想到如果要用C++来实现的话,肯定要用到函数指针。又因为非静态成员对象的调用依赖于具体的实例对象,为了能够以统一的方式存储这些函数指针就需要用多态进行封装。以下代码是利用C++特性实现的委托。

#include <iostream>
#include <list>
using namespace std;

class IDelegate
{
public:
    virtual ~IDelegate() {}
    virtual bool isType(const std::type_info &_type) = 0;
    virtual void invoke() = 0; // 回调函数
    virtual bool compare(IDelegate *_delegate) const = 0;
};

// 全局函数委托类
class CStaticDelegate : public IDelegate
{
public:
    typedef void (*Func)(); // Func是函数指针类型的别名
    CStaticDelegate(Func _func) : mFunc(_func) {}
    // 查看类是否一致
    virtual bool isType(const std::type_info &_type) { return typeid(CStaticDelegate) == _type; }

    virtual void invoke() { mFunc(); } // 通过函数指针调用全局函数

    // 输入委托基类
    virtual bool compare(IDelegate *_delegate) const
    {
        // 判断和自身的类型是否相同
        if (0 == _delegate || !_delegate->isType(typeid(CStaticDelegate)))
            return false;
        // 向下转型,判断函数地址是否相同
        CStaticDelegate *cast = static_cast<CStaticDelegate *>(_delegate);
        return cast->mFunc == mFunc;
    }

private:
    Func mFunc; // 定义私有函数指针
};

// 成员函数委托类
template <class T> // 对于成员函数委托,需要使用模版,因为不能对一个类单独化。
class CMethodDelegate : public IDelegate
{
public:
    typedef void (T::*Method)(); // 这是一个指向 T作用域下的无返回值的无参成员函数 的函数指针

    CMethodDelegate(T *_object, Method _method) : mObject(_object), mMethod(_method) {}

    virtual bool isType(const std::type_info &_type) { return typeid(CMethodDelegate<T>) == _type; }

    virtual void invoke()
    {
        (mObject->*mMethod)();
    }
    virtual bool compare(IDelegate *_delegate) const
    {
        if (0 == _delegate || !_delegate->isType(typeid(CMethodDelegate<T>)))
            return false;
        CMethodDelegate<T> *cast = static_cast<CMethodDelegate<T> *>(_delegate);
        return cast->mObject == mObject && cast->mMethod == mMethod;
    }

private:
    T *mObject;     // 定义调用这个函数的类对象指针,因为调用成员函数需要类对象来调用
    Method mMethod; // 定义函数指针
};

// 委托管理
#if 1
class CMultiDelegate
{
public:
    // 存储委托容器
    typedef list<IDelegate *> ListDelegate;
    // 容器迭代器
    typedef ListDelegate::iterator ListDelegateIterator;
    // 容器const迭代器
    typedef ListDelegate::const_iterator ConstListDelegateIterator;

    CMultiDelegate() {}
    ~CMultiDelegate() { clear(); }

    // 是否为空
    bool empty() const
    {
        for (ConstListDelegateIterator iter = mListDelegates.begin(); iter != mListDelegates.end(); ++iter)
        {
            if (*iter)
                return false;
        }
        return true;
    }
    // 清空
    void clear()
    {
        for (ListDelegateIterator iter = mListDelegates.begin(); iter != mListDelegates.end(); ++iter)
        {
            if (*iter)
            {
                delete (*iter);
                (*iter) = 0;
            }
        }
    }
    // 添加绑定
    CMultiDelegate &operator+=(IDelegate *_delegate)
    {
        for (ListDelegateIterator iter = mListDelegates.begin(); iter != mListDelegates.end(); ++iter)
        {
            if ((*iter) && (*iter)->compare(_delegate)) // 判断是否已经存在,就不在添加
            {
                delete _delegate;
                return *this;
            }
        }
        mListDelegates.push_back(_delegate);
        return *this;
    }
    // 解开绑定
    CMultiDelegate &operator-=(IDelegate *_delegate)
    {
        for (ListDelegateIterator iter = mListDelegates.begin(); iter != mListDelegates.end(); ++iter)
        {
            if ((*iter) && (*iter)->compare(_delegate))
            {
                if ((*iter) != _delegate)
                    delete (*iter);
                (*iter) = 0;
                break;
            }
        }
        delete _delegate;
        return *this;
    }

    void operator()()
    {
        // 调用
        ListDelegateIterator iter = mListDelegates.begin();
        while (iter != mListDelegates.end())
        {
            if (0 == (*iter))
            {
                iter = mListDelegates.erase(iter);
            }
            else
            {
                (*iter)->invoke();
                ++iter;
            }
        }
    }

private:
    ListDelegate mListDelegates; // 链表容器
};
#endif
// 统一创建委托对象的回调函数
// 通过不同的函数重载,可以返回对应的委托
inline IDelegate *newDelegate(void (*_func)())
{
    return new CStaticDelegate(_func);
}

template <class T>
inline IDelegate *newDelegate(T *_object, void (T::*_method)())
{
    return new CMethodDelegate<T>(_object, _method);
}

// 测试
class TestClass
{
public:
    static void print_static()
    {
        cout << "静态函数" << endl;
    }
    void print()
    {
        cout << "成员函数" << endl;
    }
};
void print()
{
    cout << "全局函数" << endl;
}
int main()
{
    CMultiDelegate delegate;
    TestClass c;

    delegate += newDelegate(print);
    delegate += newDelegate(&TestClass::print_static); // 静态函数
    delegate += newDelegate(&c, &TestClass::print);    // 普通成员函数,对象调用

    delegate();
    return 0;
}

C语言回调函数

C语言的回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。

#include <stdio.h>

void printWelcome(int len)
{
    printf("欢迎%d\n", len);
}

void printGoodbye(int len)
{
    printf("送客%d\n", len);
}

void callback(int times, void (*print)(int))
{
    int i;
    for (i = 0; i < times; ++i)
    {
        print(i); // 调用第二个参数对应的函数
    }
}
void main(void)
{
    callback(1, printWelcome);//欢迎0
    callback(2, printGoodbye);//送客0  送客1
    printWelcome(2);//欢迎2
}

typedef的作用:一个是给变量一个易记且意义明确的新名字,另一个是简化一些比较复杂的类型声明,结合typedef可以简化回调函数类型声明。

#include <stdio.h>
typedef void (*print)();

void callback(print fun)
{
    fun();
}

void printWelcome()
{
    printf("欢迎\n");
}

void main(void)
{
    callback(printWelcome);//欢迎
}

C是一种程序设计语言,也是一门通用的高级编程语言。它由美国贝尔实验室的丹尼斯·里奇(Dennis Ritchie)和肯·汤普逊(Ken Thompson)于20世纪70年代开发出来。C语言作为一种抽象层次较低的语言,提供了丰富的底层操作,使得程序员可以更加精细地控制计算机硬件的操作。 C语言具有简洁、高效、灵活的特点,因此在计算机领域得到了广泛的应用。它可用于开发操作系统、编写嵌入式系统、实现网络通信、设计图形界面等。此外,许多其他编程语言(如C++、Java)的底层也是通过C语言实现的,因此学习C语言对于理解其他编程语言的原理和机制非常重要。 C语言的语法相对简单,主要包括基本的数据类型、变量、表达式、函数等。它也提供了丰富的控制结构,如条件语句、循环语句等,使得程序员能够编写复杂的逻辑和算法C语言还支持指针操作,这是它独有的特性,通过指针可以直接访问和操纵内存中的数据,提高了程序的运行效率。 然而,C语言也存在一些不足之处。由于它较为底层,缺乏对高级抽象的支持,因此编写大规模的程序可能会比较困难。另外,C语言对于错误处理和内存管理等方面没有自动化的支持,需要程序员自己负责,容易出现错误和内存泄漏等问题。 总的来说,C语言是一门重要且有影响力的编程语言,它为计算机领域做出了重要贡献,并在各个领域都有广泛的应用。学习C语言对于提高编程能力、理解底层原理和深入学习其他编程语言都具有重要意义。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值