アリスはプラダがお好き

プラダの鞄を直接あげるのが値渡し | Moonmile Solutions Blog
http://www.moonmile.net/blog/archives/1431
プラダの鞄をおねだりするのが参照 | Moonmile Solutions Blog
http://www.moonmile.net/blog/archives/1434
アリスはプラダの中古がお嫌い | Moonmile Solutions Blog
http://www.moonmile.net/blog/archives/1442

プラダの鞄シリーズを再開w

ってな訳で、ちょっと C++ で組んでみました。
Bag クラスを基底クラスにして、Prada と Tiffany クラスを作ります。そして、ルイスが尋ねるのです。 Do you like this ?

なので、Alice クラスに DoYouLike メソッドを追加して Bag を渡すとどうなるでしょうか?

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
53
54
55
56
57
58
59
60
61
#include <iostream>
 
class Bag {
protected:
    bool used ;
public:
    virtual void setUsed() { used = true; }
};
class Prada : public Bag {};
class Tiffany : public Bag {};
 
#if 0
// おバカなアリス
class Alice
{
public:
    bool DoYouLike( void *bug )
    {
        return true;
    }
};
#else
// 賢いアリス
class Alice
{
public:
    bool DoYouLike( Bag *bag )
    {
        Prada *prada = dynamic_cast<Prada*>(bag);
        if ( prada == NULL ) {
            return false;
        } else {
            return true;
        }
    }
};
#endif
 
using namespace std;
int main(void)
{
 
    Alice alice;
    {
        Prada bag;;
        if ( alice.DoYouLike( &bag ) ) {
            cout << "alice like Prada." << endl;
        } else {
            cout << "alice don't like Prada." << endl;
        }
    }
    {
        Tiffany bag;;
        if ( alice.DoYouLike( &bag ) ) {
            cout << "alice like Tiffany." << endl;
        } else {
            cout << "alice don't like Tiffany." << endl;
        }
    }
    return 0;
}

おバカなアリスのほうは、Bag が貰えたらそれで嬉しいので、true を返します。メソッドを見ると分かりますが、何も考えていませんね。

賢いアリスのほうは、dynmaic_cast を使ってアップキャストをします。Prada も Tiffany も Bag クラスを継承しているので、DoYouLike メソッドには Bag* で渡すのですが、これが Prada なのか Tiffany なのかを Alice 自身が判断します。

1
2
3
D:\work\blog\src\alice>a
alice like Prada.
alice don't like Tiffany.

そうすると、こんな風に、Prada の鞄だけを好みます。
この判別の仕方、ちょっとなんだかなぁと思うのは、

  • 基底クラスに virtual なメソッドをひとつ必要とする。
  • dynamic_cast でキャストを実行するのじゃなくて、元の型を判別したいなぁ。

ってところですね。virtual メソッドは、dynamic_cast の制限のひとつで(でいいのかな?)、ひとつだけ仮想関数がないと駄目なんです。
キャストを実行せずに、元の型をというのは、多分 Java や C# のような型をランタイムで持っている言語じゃないと難しいと思います。そもそも C++ は型自身はメモリ上に持っていませんからね。単なる構造体と変わらないのです(v_tblとか)。

ちなみに C# で書くとこんな感じ。

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
using System;
 
public class Bag {}
public class Prada : Bag {}
public class Tiffany : Bag {}
 
public class Alice {
    public bool DoYouLike( Bag bag ) {
        if ( bag as Prada != null ) {
            return true;
        } else {
            return false;
        }
    }
}
 
public class Program {
    public static void Main(string []args ) {
        Alice alice = new Alice();
         
        Prada prada = new Prada();
        if ( alice.DoYouLike( prada ) ) {
            Console.WriteLine("alice likes prada.");
        } else {
            Console.WriteLine("alice don's likes prada.");
        }
 
        Tiffany tiffaniy = new Tiffany();
        if ( alice.DoYouLike( tiffaniy ) ) {
            Console.WriteLine("alice likes tiffaniy.");
        } else {
            Console.WriteLine("alice don's likes tiffaniy.");
        }
    }
}

やっぱり as 演算子でキャストして試してみるのが良さそうです。

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