ルイスはアリスに電話する

誰かが使ったらアリスに知らせろ | Moonmile Solutions Blog
http://www.moonmile.net/blog/archives/2017
誰かが使ったらアリスに知らせろ(2) | Moonmile Solutions Blog
http://www.moonmile.net/blog/archives/2023

なところで、イベントを受信するパターンを書いたわけですが、これを使うと電話が作れます。いわゆる、

  • 電話を掛けるというコネクション
  • 電話を受けるという非同期イベント

な感じです。電話を受けるときには、電話番をしている訳ではなくて(電話番の場合はポーリングな訳ですが)、電話のベルが鳴ったら受話器を取るという、非同期的なイベントになります。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
// for ルイスはアリスに電話する
 
#include <string.h>
#include <iostream>
using namespace std;
 
class ITelephone {
protected:
    ITelephone *_person;
public:
    // 相手先を登録
    void setPhone( ITelephone *person ) {
        this->_person = person ;
    }
    // データを送信
    virtual void sendData( const void *data, int size ) {
        if ( _person != NULL ) {
            _person->onPhone(data,size);
        }
    }
    // データを受信する仮想関数
    virtual void onPhone( const void *data, int size ) = 0;
};
 
class Person : public ITelephone
{
public:
    char _name[30];
public:
    Person( const char *name ) {
        strcpy( _name, name );
    }
    virtual void onPhone( const void *data, int size ) {
        cout << "to " << _name << ": " << (char*)data << endl;
    }
    virtual void sendData( const void *data, int size ) {
        cout << "from " << _name << ": " << (char*)data << endl;
        ITelephone::sendData( data, size );
    }
};
 
int main(void)
{
    Person alice("alice");
    Person lewis("lewis");
 
    // アリスに電話を掛ける。
    lewis.setPhone( &alice );
    lewis.sendData( "hello i'm lewis", 0 );
 
    return 0;
}

これを実行するとこんな感じ。

1
2
3
D:\work\blog\src\alice>a
from lewis: hello i'm lewis
to alice: hello i'm lewis

ルイスからアリスに電話を掛けると、アリスの onPhone メソッドが呼び出されるという仕組みです。
実は、この ITelephone インターフェースは、Person で継承しているために、

人に電話が内蔵されている

って意味になっていますがw、ま、気にせずにッ!!! 単純に継承したほうが、機能拡張は楽だというオブジェクト指向の落とし穴に陥った例です。2,3 機能追加であれば、このように直で継承するほうがいいのですが、これの数が増えてしまう場合には、委譲という形で機能を分離したほうがよいのです。

人が電話を持っているパターンは次回に作り直します。

カテゴリー: C++ パーマリンク