C++ 设计模式——职责链模式

2024-08-31 19:52
文章标签 c++ 设计模式 模式 职责

本文主要是介绍C++ 设计模式——职责链模式,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

    • C++ 设计模式——职责链模式
      • 1. 主要组成成分
      • 2. 逐步构建职责链模式
        • 步骤1:定义处理者接口
        • 步骤2:定义抽象处理者
        • 步骤3: 创建具体处理者
        • 步骤4: 配置职责链
      • 3. 备忘录模式 UML 图
        • UML 图解析
      • 4. 单纯与非单纯的职责链模式
        • 4.1 敏感词过滤器父类
        • 4.2 具体过滤器实现
        • 4.3 主函数
      • 5. 职责链模式的优点
      • 6. 职责链模式的缺点
      • 7. 职责链模式的适用场景
      • 总结
      • 完整代码

C++ 设计模式——职责链模式

职责链(Chain Of Responsibility)模式也叫责任链模式,是一种行为型模式,用于将一个请求传递给一个链中的若干对象,哪个对象适合处理这个请求就让哪个对象来处理。职责链看起来与传统数据结构中的“链表”非常类似。

引人“职责链”设计模式的定义(实现意图):使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链(构成对象链),并沿着这条链传递该请求,直到有一个对象处理它为止。

1. 主要组成成分

  1. 处理器接口(Handler Interface):定义了一个处理请求的接口,通常包含一个方法用于接收或处理请求。这个接口不确定请求的具体处理者。
  2. 具体处理器(Concrete Handlers):实现处理器接口的类。每个处理器会对请求做出处理或者将请求传递给链中的下一个处理者。具体处理器决定了处理请求的条件和方式。
  3. 请求类(Request):通常是包含多个属性的类,这些属性决定了哪个具体处理器应该处理该请求。
  4. 客户端(Client):负责创建处理链,并向链的第一个处理器发送请求。客户端不关心请求如何以及由谁处理,这样做实现了发送者和接收者之间的解耦。

2. 逐步构建职责链模式

以下示例展示了如何实现一个用于处理加薪请求的职责链模式。此示例包含三个不同级别的审批者:部门经理、技术总监和总经理,各自能够处理特定范围的加薪请求。以下是构建职责链模式的详细步骤:

步骤1:定义处理者接口

已定义 RaiseRequest 类封装了加薪请求,其中包括员工姓名和加薪金额。

//加薪请求类
class RaiseRequest
{
public://构造函数RaiseRequest(const string& sname, int salfigure) :m_sname(sname), m_isalfigure(salfigure) {}//获取请求加薪的人员名字const string& getName() const{return m_sname;}//获取请求加薪的数字int getSalFigure() const{return m_isalfigure;}private:string m_sname;      //请求加薪的人员名字int    m_isalfigure; //请求加薪的数字
};
步骤2:定义抽象处理者

定义了一个名为 ParSalApprover 的抽象基类,其中包含一个处理请求的纯虚函数 processRequest 和一个函数 setNextChain 用于设置链中的下一个处理者。

//薪水审批者父类
class ParSalApprover
{
public:ParSalApprover() :m_nextChain(nullptr) {}virtual ~ParSalApprover() {} //做父类时析构函数应该为虚函数//设置指向的职责链中的下个审批者void setNextChain(ParSalApprover* next){m_nextChain = next;}//处理加薪请求virtual void processRequest(const RaiseRequest& req) = 0;protected://找链中的下个对象并把请求投递给下个链中的对象void sendRequestToNextHandler(const RaiseRequest& req){//找链中的下个对象if (m_nextChain != nullptr){//把请求投递给链中的下个对象m_nextChain->processRequest(req);}else{//没找到链中的下个对象,程序流程执行这里似乎不应该cout << req.getName() << "的加薪要求为:" << req.getSalFigure() << "元,但无人能够审批!" << endl;}}private:ParSalApprover* m_nextChain; //指向下一个审批者(对象)的多态指针(指向自身类型),每个都指向下一个,就会构成一个职责链(链表)
};
步骤3: 创建具体处理者

创建了三个具体处理者:depManager_SA, CTO_SA, 和 genManager_SA,每个类根据其规则处理请求。

//部门经理子类
class depManager_SA :public ParSalApprover
{
public://处理加薪请求virtual void processRequest(const RaiseRequest& req){int salfigure = req.getSalFigure();if (salfigure <= 1000){//如果自己能处理,则自己处理cout << req.getName() << "的加薪要求为:" << salfigure << "元,部门经理审批通过!" << endl;}else{//自己不能处理,尝试找链中的下个对象来处理sendRequestToNextHandler(req);}}
};//技术总监子类
class CTO_SA :public ParSalApprover
{//处理加薪请求virtual void processRequest(const RaiseRequest& req){int salfigure = req.getSalFigure();if (salfigure > 1000 && salfigure <= 5000){//如果自己能处理,则自己处理cout << req.getName() << "的加薪要求为:" << salfigure << "元,技术总监审批通过!" << endl;}else{sendRequestToNextHandler(req);//自己不能处理,尝试找链中的下个对象来处理}}
};//总经理子类
class genManager_SA :public ParSalApprover
{
public://处理加薪请求virtual void processRequest(const RaiseRequest& req){int salfigure = req.getSalFigure();if (salfigure > 5000){//如果自己能处理,则自己处理cout << req.getName() << "的加薪要求为:" << salfigure << "元,总经理审批通过!" << endl;}else{sendRequestToNextHandler(req);//自己不能处理,尝试找链中的下个对象来处理}}
};
步骤4: 配置职责链

在主函数中,创建处理者对象,并按逻辑顺序将它们连接起来形成一个链。

int main()
{//(1)创建出职责链中包含的各个对象(部门经理、技术总监、总经理)ParSalApprover* pzzlinkobj1 = new depManager_SA();ParSalApprover* pzzlinkobj2 = new CTO_SA();ParSalApprover* pzzlinkobj3 = new genManager_SA();//(2)将这些对象串在一起构成职责链(链表),现在职责链中pzzlinkobj1排在最前面,pzzlinkobj3排在最后面pzzlinkobj1->setNextChain(pzzlinkobj2);pzzlinkobj2->setNextChain(pzzlinkobj3);pzzlinkobj3->setNextChain(nullptr); //可以不写此行,因为ParSalApprover构造函数中设置了m_nextChain为nullptr//(3)创建几位员工关于加薪的请求(对象)RaiseRequest emp1Req("张三", 15000);//张三要求加薪1.5万RaiseRequest emp2Req("李四", 3500);//李四要求加薪3千5RaiseRequest emp3Req("王二", 800);//王二要求加薪8百//看看每位员工的加薪请求由职责链中的哪个对象(部门经理、技术总监、总经理)来处理,从职责链中排在最前面的接收者(pzzlinkobj1)开始pzzlinkobj1->processRequest(emp1Req);pzzlinkobj1->processRequest(emp2Req);pzzlinkobj1->processRequest(emp3Req);//(4)释放资源delete pzzlinkobj1;delete pzzlinkobj2;delete pzzlinkobj3;return 0;
}

3. 备忘录模式 UML 图

职责链模式 UML 图

UML 图解析

职责链模式的 UML 图中包含3种角色:

  1. Handler (处理者):
    • 作用:定义处理请求的接口(通常为 processRequest),同时也记录了链中下一个处理者的引用(在本例中使用 m_nextChain 来记录)。
    • 实现:在示例中,ParSalApprover 类扮演此角色,提供了设置下一个处理者和处理请求的基本框架。
  2. ConcreteHandler (具体处理者):
    • 作用:实现具体请求的处理逻辑。如果当前处理者无法完全处理请求,则将请求传递给链中的下一个处理者(后继者)。
    • 实现:在示例中,depManager_SACTO_SAgenManager_SA 类是具体处理者。每个类都有条件判断是否能处理请求,不能处理时将请求传递给链上的下一个处理者。
  3. Client (请求者/客户端):
    • 作用:向职责链上的具体处理者对象提交处理请求。客户端负责初始化处理链并触发请求处理过程。
    • 实现:在示例中,主函数 main 执行了客户端的角色。除了提交处理请求,它还负责创建职责链对象并搭建职责链。这部分通常是由客户端完成,因为职责链的结构和顺序可能根据不同的业务场景需要不同的配置。

4. 单纯与非单纯的职责链模式

在设计模式中,职责链模式可以分为两种形式:单纯的职责链模式和非单纯的职责链模式。这两种形式主要区别在于请求在链中的传递方式和处理者的责任范围。非单纯的职责链模式中允许一个请求被某个接收者处理后继续沿着职责链传递,其他处理者仍有机会继续处理该请求,这样的职责链往往也被称为功能链,即便一个请求未被任何处理者对象处理,在非单纯的职责链模式中也是允许的。功能链一般用于权限的多次多重校验、数据的多重检查和过滤等场合。

下面给出这个敏感词过滤器非单纯职责链模式范例(参照前面的范例书写即可)。该过滤器能够把聊天内容中涉及性、脏话、政治内容的关键词寻找出来并用一些其他符号来代替。首先创建敏感词过滤器父类,代码如下:

4.1 敏感词过滤器父类

定义一个抽象基类,其中包含将请求传递给链中下一个处理者的方法。

//敏感词过滤器父类
class ParWordFilter
{
public:ParWordFilter() :m_nextChain(nullptr) {}virtual ~ParWordFilter() {} //做父类时析构函数应该为虚函数//设置指向的职责链中的下个过滤器void setNextChain(ParWordFilter* next){m_nextChain = next;}//处理敏感词过滤请求virtual string processRequest(string strWord) = 0;protected://找链中的下个对象并把请求投递给下个链中的对象string sendRequestToNextHandler(string strWord){//找链中的下个对象if (m_nextChain != nullptr){//把请求投递给链中的下个对象return m_nextChain->processRequest(strWord);}return strWord;}
private:ParWordFilter* m_nextChain;
};
4.2 具体过滤器实现

接着,创建敏感词过滤器子类共3个,分别用于过滤性、脏话、政治内容,代码如下:

//性敏感词过滤器子类
class SexyWordFilter :public ParWordFilter
{
public:virtual string processRequest(string strWord){cout << "通过与词库比对,在strWord中查找\"性\"敏感词并用XXX来替换!" << endl;strWord += "XXX"; //测试代码,具体的实现逻辑略......return sendRequestToNextHandler(strWord);}
};//脏话词过滤器子类
class DirtyWordFilter :public ParWordFilter
{
public:virtual string processRequest(string strWord){cout << "通过与词库比对,在strWord中查找\"脏话\"敏感词并用YYY来替换!" << endl;strWord += "YYY";return sendRequestToNextHandler(strWord);}
};//政治敏感词过滤器子类
class PoliticsWordFilter :public ParWordFilter
{
public:virtual string processRequest(string strWord){cout << "通过与词库比对,在strWord中查找\"政治\"敏感词并用ZZZ来替换!" << endl;strWord += "ZZZ";return sendRequestToNextHandler(strWord);}
};
4.3 主函数

在主函数中创建和配置职责链。

int main()
{  //(1)创建出职责链中包含的各个对象(性敏感词过滤器、脏话词过滤器、政治敏感词过滤器)ParWordFilter* pwflinkobj1 = new SexyWordFilter();ParWordFilter* pwflinkobj2 = new DirtyWordFilter();ParWordFilter* pwflinkobj3 = new PoliticsWordFilter();//(2)将这些对象串在一起构成职责链(链表),现在职责链中pwflinkobj1排在最前面,pwflinkobj3排在最后面pwflinkobj1->setNextChain(pwflinkobj2);pwflinkobj2->setNextChain(pwflinkobj3);pwflinkobj3->setNextChain(nullptr);string strWordFilterResult = pwflinkobj1->processRequest("你好,这里是过滤敏感词测试范例"); //从职责链中排在最前面的接收者(pwflinkobj1)开始,processRequest的参数代表的是聊天内容cout << "对敏感词过滤后的结果为:" << strWordFilterResult << endl;//(3)释放资源delete pwflinkobj1;delete pwflinkobj2;delete pwflinkobj3;return 0;
}

执行结果:

通过与词库比对,在strWord中查找"性"敏感词并用XXX来替换!
通过与词库比对,在strWord中查找"脏话"敏感词并用YYY来替换!
通过与词库比对,在strWord中查找"政治"敏感词并用ZZZ来替换!
对敏感词过滤后的结果为:你好,这里是过滤敏感词测试范例XXXYYYZZZ

从结果可以看到,聊天内容(请求)先经过性敏感词过滤器处理,然后再把处理后的聊天内容(请求)传递给脏话敏感词过滤器,脏话敏感词过滤器处理完后再传递给政治敏感词过滤器,这些过滤器形成了一个链条。链条上的每个过滤器各自承担自己的处理职责,经过多次被处理并被放行传递到下一个过滤器的过程,最终处理结果被返回到strWordFilterResult中。

5. 职责链模式的优点

  • 减少请求的发送者和接收者之间的耦合:发送者和接收者不需要知道彼此的具体细节。
  • 增强了系统的灵活性:可以动态地添加或修改处理链,而不影响其他部分。
  • 增强了给定请求的处理机会:请求可以被多个对象处理,不必绑定到特定的处理者。

6. 职责链模式的缺点

  • 请求可能未被处理:如果链配置不当,请求可能会到达链的末端而未被处理。
  • 性能问题:在某些情况下,由于需要在链上进行多次处理判断,可能会引入性能瓶颈。
  • 调试困难:由于处理过程的动态性,可能难以跟踪请求在链中的传递路径。

7. 职责链模式的适用场景

  1. 多个对象可以处理同一请求:当多个对象都可能对请求进行处理,但具体由哪个对象处理在运行时才确定时,职责链模式提供了一种灵活的处理方式。
  2. 不明确具体接收者:在请求的发送者不需要知道请求的具体接收者是谁的情况下,使用职责链模式可以将发送者和接收者解耦。
  3. 可动态指定处理的顺序:当需要在运行时动态改变请求处理者的顺序或者动态添加新的处理者时,职责链模式能够提供这种灵活性。

总结

职责链模式通过建立一条对象链来处理请求,实现了请求发送者和接收者之间的解耦。它在处理具有不同处理级别的请求时特别有用,如日志记录、异常处理等场景。然而,使用时需要注意避免请求在链中过度传递,以及确保所有请求都能得到适当处理。

完整代码

#include <iostream>
using namespace std;//加薪请求类
class RaiseRequest
{
public://构造函数RaiseRequest(const string& sname, int salfigure) :m_sname(sname), m_isalfigure(salfigure) {}//获取请求加薪的人员名字const string& getName() const{return m_sname;}//获取请求加薪的数字int getSalFigure() const{return m_isalfigure;}private:string m_sname;      //请求加薪的人员名字int    m_isalfigure; //请求加薪的数字
};//-------------------
//薪水审批者父类
class ParSalApprover
{
public:ParSalApprover() :m_nextChain(nullptr) {}virtual ~ParSalApprover() {} //做父类时析构函数应该为虚函数//设置指向的职责链中的下个审批者void setNextChain(ParSalApprover* next){m_nextChain = next;}//处理加薪请求virtual void processRequest(const RaiseRequest& req) = 0;protected://找链中的下个对象并把请求投递给下个链中的对象void sendRequestToNextHandler(const RaiseRequest& req){//找链中的下个对象if (m_nextChain != nullptr){//把请求投递给链中的下个对象m_nextChain->processRequest(req);}else{//没找到链中的下个对象,程序流程执行这里似乎不应该cout << req.getName() << "的加薪要求为:" << req.getSalFigure() << "元,但无人能够审批!" << endl;}}private:ParSalApprover* m_nextChain; //指向下一个审批者(对象)的多态指针(指向自身类型),每个都指向下一个,就会构成一个职责链(链表)
};//部门经理子类
class depManager_SA :public ParSalApprover
{
public://处理加薪请求virtual void processRequest(const RaiseRequest& req){int salfigure = req.getSalFigure();if (salfigure <= 1000){//如果自己能处理,则自己处理cout << req.getName() << "的加薪要求为:" << salfigure << "元,部门经理审批通过!" << endl;}else{//自己不能处理,尝试找链中的下个对象来处理sendRequestToNextHandler(req);}}
};//技术总监子类
class CTO_SA :public ParSalApprover
{//处理加薪请求virtual void processRequest(const RaiseRequest& req){int salfigure = req.getSalFigure();if (salfigure > 1000 && salfigure <= 5000){//如果自己能处理,则自己处理cout << req.getName() << "的加薪要求为:" << salfigure << "元,技术总监审批通过!" << endl;}else{sendRequestToNextHandler(req);//自己不能处理,尝试找链中的下个对象来处理}}
};//总经理子类
class genManager_SA :public ParSalApprover
{
public://处理加薪请求virtual void processRequest(const RaiseRequest& req){int salfigure = req.getSalFigure();if (salfigure > 5000){//如果自己能处理,则自己处理cout << req.getName() << "的加薪要求为:" << salfigure << "元,总经理审批通过!" << endl;}else{sendRequestToNextHandler(req);//自己不能处理,尝试找链中的下个对象来处理}}
};//敏感词过滤器父类
class ParWordFilter
{
public:ParWordFilter() :m_nextChain(nullptr) {}virtual ~ParWordFilter() {} //做父类时析构函数应该为虚函数//设置指向的职责链中的下个过滤器void setNextChain(ParWordFilter* next){m_nextChain = next;}//处理敏感词过滤请求virtual string processRequest(string strWord) = 0;protected://找链中的下个对象并把请求投递给下个链中的对象string sendRequestToNextHandler(string strWord){//找链中的下个对象if (m_nextChain != nullptr){//把请求投递给链中的下个对象return m_nextChain->processRequest(strWord);}return strWord;}
private:ParWordFilter* m_nextChain;
};//性敏感词过滤器子类
class SexyWordFilter :public ParWordFilter
{
public:virtual string processRequest(string strWord){cout << "通过与词库比对,在strWord中查找\"性\"敏感词并用XXX来替换!" << endl;strWord += "XXX"; //测试代码,具体的实现逻辑略......return sendRequestToNextHandler(strWord);}
};//脏话词过滤器子类
class DirtyWordFilter :public ParWordFilter
{
public:virtual string processRequest(string strWord){cout << "通过与词库比对,在strWord中查找\"脏话\"敏感词并用YYY来替换!" << endl;strWord += "YYY";return sendRequestToNextHandler(strWord);}
};//政治敏感词过滤器子类
class PoliticsWordFilter :public ParWordFilter
{
public:virtual string processRequest(string strWord){cout << "通过与词库比对,在strWord中查找\"政治\"敏感词并用ZZZ来替换!" << endl;strWord += "ZZZ";return sendRequestToNextHandler(strWord);}
};int main()
{//(1)创建出职责链中包含的各个对象(部门经理、技术总监、总经理)ParSalApprover* pzzlinkobj1 = new depManager_SA();ParSalApprover* pzzlinkobj2 = new CTO_SA();ParSalApprover* pzzlinkobj3 = new genManager_SA();//(2)将这些对象串在一起构成职责链(链表),现在职责链中pzzlinkobj1排在最前面,pzzlinkobj3排在最后面pzzlinkobj1->setNextChain(pzzlinkobj2);pzzlinkobj2->setNextChain(pzzlinkobj3);pzzlinkobj3->setNextChain(nullptr); //可以不写此行,因为ParSalApprover构造函数中设置了m_nextChain为nullptr//(3)创建几位员工关于加薪的请求(对象)RaiseRequest emp1Req("张三", 15000);//张三要求加薪1.5万RaiseRequest emp2Req("李四", 3500);//李四要求加薪3千5RaiseRequest emp3Req("王二", 800);//王二要求加薪8百//看看每位员工的加薪请求由职责链中的哪个对象(部门经理、技术总监、总经理)来处理,从职责链中排在最前面的接收者(pzzlinkobj1)开始pzzlinkobj1->processRequest(emp1Req);pzzlinkobj1->processRequest(emp2Req);pzzlinkobj1->processRequest(emp3Req);//(4)释放资源delete pzzlinkobj1;delete pzzlinkobj2;delete pzzlinkobj3;//(1)创建出职责链中包含的各个对象(性敏感词过滤器、脏话词过滤器、政治敏感词过滤器)ParWordFilter* pwflinkobj1 = new SexyWordFilter();ParWordFilter* pwflinkobj2 = new DirtyWordFilter();ParWordFilter* pwflinkobj3 = new PoliticsWordFilter();//(2)将这些对象串在一起构成职责链(链表),现在职责链中pwflinkobj1排在最前面,pwflinkobj3排在最后面pwflinkobj1->setNextChain(pwflinkobj2);pwflinkobj2->setNextChain(pwflinkobj3);pwflinkobj3->setNextChain(nullptr);string strWordFilterResult = pwflinkobj1->processRequest("你好,这里是过滤敏感词测试范例"); //从职责链中排在最前面的接收者(pwflinkobj1)开始,processRequest的参数代表的是聊天内容cout << "对敏感词过滤后的结果为:" << strWordFilterResult << endl;//(3)释放资源delete pwflinkobj1;delete pwflinkobj2;delete pwflinkobj3;return 0;
}

这篇关于C++ 设计模式——职责链模式的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1124850

相关文章

C++初始化数组的几种常见方法(简单易懂)

《C++初始化数组的几种常见方法(简单易懂)》本文介绍了C++中数组的初始化方法,包括一维数组和二维数组的初始化,以及用new动态初始化数组,在C++11及以上版本中,还提供了使用std::array... 目录1、初始化一维数组1.1、使用列表初始化(推荐方式)1.2、初始化部分列表1.3、使用std::

C++ Primer 多维数组的使用

《C++Primer多维数组的使用》本文主要介绍了多维数组在C++语言中的定义、初始化、下标引用以及使用范围for语句处理多维数组的方法,具有一定的参考价值,感兴趣的可以了解一下... 目录多维数组多维数组的初始化多维数组的下标引用使用范围for语句处理多维数组指针和多维数组多维数组严格来说,C++语言没

c++中std::placeholders的使用方法

《c++中std::placeholders的使用方法》std::placeholders是C++标准库中的一个工具,用于在函数对象绑定时创建占位符,本文就来详细的介绍一下,具有一定的参考价值,感兴... 目录1. 基本概念2. 使用场景3. 示例示例 1:部分参数绑定示例 2:参数重排序4. 注意事项5.

使用C++将处理后的信号保存为PNG和TIFF格式

《使用C++将处理后的信号保存为PNG和TIFF格式》在信号处理领域,我们常常需要将处理结果以图像的形式保存下来,方便后续分析和展示,C++提供了多种库来处理图像数据,本文将介绍如何使用stb_ima... 目录1. PNG格式保存使用stb_imagephp_write库1.1 安装和包含库1.2 代码解

Java实现状态模式的示例代码

《Java实现状态模式的示例代码》状态模式是一种行为型设计模式,允许对象根据其内部状态改变行为,本文主要介绍了Java实现状态模式的示例代码,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来... 目录一、简介1、定义2、状态模式的结构二、Java实现案例1、电灯开关状态案例2、番茄工作法状态案例

C++实现封装的顺序表的操作与实践

《C++实现封装的顺序表的操作与实践》在程序设计中,顺序表是一种常见的线性数据结构,通常用于存储具有固定顺序的元素,与链表不同,顺序表中的元素是连续存储的,因此访问速度较快,但插入和删除操作的效率可能... 目录一、顺序表的基本概念二、顺序表类的设计1. 顺序表类的成员变量2. 构造函数和析构函数三、顺序表

使用C++实现单链表的操作与实践

《使用C++实现单链表的操作与实践》在程序设计中,链表是一种常见的数据结构,特别是在动态数据管理、频繁插入和删除元素的场景中,链表相比于数组,具有更高的灵活性和高效性,尤其是在需要频繁修改数据结构的应... 目录一、单链表的基本概念二、单链表类的设计1. 节点的定义2. 链表的类定义三、单链表的操作实现四、

使用C/C++调用libcurl调试消息的方式

《使用C/C++调用libcurl调试消息的方式》在使用C/C++调用libcurl进行HTTP请求时,有时我们需要查看请求的/应答消息的内容(包括请求头和请求体)以方便调试,libcurl提供了多种... 目录1. libcurl 调试工具简介2. 输出请求消息使用 CURLOPT_VERBOSE使用 C

C++实现获取本机MAC地址与IP地址

《C++实现获取本机MAC地址与IP地址》这篇文章主要为大家详细介绍了C++实现获取本机MAC地址与IP地址的两种方式,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 实际工作中,项目上常常需要获取本机的IP地址和MAC地址,在此使用两种方案获取1.MFC中获取IP和MAC地址获取

C/C++通过IP获取局域网网卡MAC地址

《C/C++通过IP获取局域网网卡MAC地址》这篇文章主要为大家详细介绍了C++如何通过Win32API函数SendARP从IP地址获取局域网内网卡的MAC地址,感兴趣的小伙伴可以跟随小编一起学习一下... C/C++通过IP获取局域网网卡MAC地址通过win32 SendARP获取MAC地址代码#i