C++用纯虚函数实现协议委托的例子

6 篇文章 0 订阅

C++用纯虚函数实现协议委托的例子

标签: 协议委托纯虚函数回调函数式编程
  2017人阅读  评论(6)  收藏  举报
  分类:

  C++不像其他很多编程语言有接口、委托或者协议的概念,但是利用纯虚函数和C++多重继承的特性,我们也能实现接口、委托或协议要做的事情,下面的通过一个人设置闹钟然后被闹钟唤醒的例子来说明如何在C++中实现委托回调。

<code class="language-C++ hljs cpp has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;"><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#include <iostream></span>
<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#include <unistd.h></span>

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">using</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span>::<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">cout</span>;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">using</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span>::endl;

<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 用纯虚函数设计一个协议</span>
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 实现该协议的类有一个被唤醒的行为</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> Awakable {
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span>:
    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 纯虚函数</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">virtual</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> beAwaken() = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;
};

<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 闹钟类</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> AlarmClock {
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span>:
    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 委托方(谁委托了闹钟提供唤醒服务)</span>
    Awakable *delegate;
    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 在指定时间后报警</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> alarmAfter(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>) <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span>;
};

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> AlarmClock::alarmAfter(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> seconds) <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span> {
    sleep(seconds);
    <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">cout</span> << <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"叮咚 叮咚 叮咚"</span> << endl;
    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 回调委托方的方法</span>
    delegate->beAwaken();
}

<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 人类(实现了Awakable协议可以被唤醒)</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> Person : <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> Awakable {
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span>:
    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 启动闹钟并指定唤醒时间</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> rollClock(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>);
    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 协议中的被唤醒的行为</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> beAwaken();
};

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> Person::rollClock(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> seconds) {
    <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">cout</span> << <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"人设置了闹钟"</span> << seconds << <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"秒后响铃"</span> << endl;
    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 在栈上创建闹钟对象</span>
    AlarmClock ac;
    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 设置委托方</span>
    ac.delegate = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>;
    ac.alarmAfter(seconds); 
}

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> Person::beAwaken() {
    <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">cout</span> << <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"人被闹钟唤醒了"</span> << endl;
}

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> main(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span>) {
    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 在堆上创建人的对象</span>
    Person *person = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Person;
    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 人启动闹钟设置5秒后被唤醒</span>
    person->rollClock(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span>);
    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 释放指针指向的堆空间</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">delete</span> person;
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li><li style="box-sizing: border-box; padding: 0px 5px;">60</li><li style="box-sizing: border-box; padding: 0px 5px;">61</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li><li style="box-sizing: border-box; padding: 0px 5px;">60</li><li style="box-sizing: border-box; padding: 0px 5px;">61</li></ul>

  程序写到这里,我相信已经不用更多的言语来解释如何实现协议委托了。其实各种编程语言的表象千变万化但是实质几乎没有区别。类似的功能在Java中用接口(interface)可以做到,在C#中可以使用委托(delegate),在Objective-C中可以使用协议(protocol),Swift中也有协议这个概念。但是如果你能够理解函数式编程的理念,还有更简单有效的方式就是使用Lambda函数,将一个回调函数直接作为参数传入一个函数或方法中,而Java(Java 8)和C#中都提供了Lambda表达式,OC中也有block来实现相同的功能。那么C++呢,别忘了C++中还有仿函数(函数对象)的概念,这些不都是一致的吗?当然,支持函数式编程范式的语言就更不用说了,就像JavaScript中可以把函数传入函数中,Swift不也是如此吗?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当一个类中有至少一个函数,我们称之为抽象类。抽象类不能被实例化,只能被继承。在抽象类中定义的函数不需要实现。但是,如果抽象类中有成员变量需要在析构函数中被释放,那么该类的析构函数必须被定义。 下面是一个例子,展示如何在抽象类中定义函数和析构函数实现: ```c++ #include <iostream> class Shape { public: virtual ~Shape() = 0; // 析构函数 virtual void draw() = 0; // 函数 void setX(int x) { this->x = x; } void setY(int y) { this->y = y; } int getX() const { return x; } int getY() const { return y; } protected: int x; int y; }; Shape::~Shape() { std::cout << "Shape destructor called." << std::endl; } class Circle : public Shape { public: void draw() override { std::cout << "Drawing a circle at (" << getX() << ", " << getY() << ")" << std::endl; } }; class Rectangle : public Shape { public: void draw() override { std::cout << "Drawing a rectangle at (" << getX() << ", " << getY() << ")" << std::endl; } }; int main() { Shape* shapes[2] = {new Circle(), new Rectangle()}; shapes[0]->setX(10); shapes[0]->setY(20); shapes[1]->setX(30); shapes[1]->setY(40); for(int i = 0; i < 2; i++) { shapes[i]->draw(); delete shapes[i]; } return 0; } ``` 在这个例子中,我们定义了一个抽象类 `Shape`,其中包含一个函数 `draw()` 和一个成员变量。由于 `Shape` 是一个抽象类,因此其析构函数必须是一个析构函数。在 `Shape` 的析构函数中,我们打印一条消息,以便在对象被销毁时进行调试。 我们还定义了两个继承自 `Shape` 的类:`Circle` 和 `Rectangle`。这两个类都实现了 `draw()` 函数。 在 `main()` 函数中,我们创建了一个 `Shape` 指针类型的数组,并使用 `new` 运算符在堆上创建了两个对象:`Circle` 和 `Rectangle`。我们设置了每个对象的 `x` 和 `y` 坐标,并调用了它们的 `draw()` 函数。最后,我们使用 `delete` 运算符释放了数组中的每个对象。 该程序的输出应该如下所示: ``` Drawing a circle at (10, 20) Shape destructor called. Drawing a rectangle at (30, 40) Shape destructor called. ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值