まず初めにお詫びをいたします。C++プログラマーが陥るC#の罠にまんまとはまり、図らずもブログネタを作ってしまいました。

昨日書いたブログの中のC#でnewしたインスタンスをで遊んだ後、優しいMicrosoftお母さんがお片づけ(ガーベージコレクション)をしてくれるのですが、C++でnewして遊んだ後は自分でお片づけ(deleteによるメモリー領域の開放)をしないと厳格なC++お母さんに「メモリーリークだよ」としかられます。(昨日のブログのコードに本日赤字"delete mc[i];"を追加しておきました。自動開放はしないので、配列の開放(デストラクター)の順序はプログラミングによる、と言えます。)

 

あと、ちょっとびっくりしたのは、C#の実行ファイルの小ささです。(constructor01-destructor01.exeは5Kバイト弱)C++の方は145KBもあります。(注)

注:もともとbcc32cでコンソールプログラムをコンパイルするとランタイムを組み込むので結構大きくなります。ウィンドウズプログラムの方がOSのサービスを呼び出すだけなのでコンパクトです。OSを知り尽くしたMicrosoftが作ったC#でもそういうことが言えると思います。...それで思い出したのは、私がシンガポールでbcc55でC++を書いていた時にC#がリリースされ、当時はまだ今のように機能が豊富ではなく「プラットフォームはWindowsだけの、C++またはJavaのMicrosoft方言」なので当分見送ってよい、という話です。あれから20年10回のバージョンアップを経てクロスプラットフォーム化(.NET)に至ったんですねぇ。

 

さて、本日のお題は関数(おっとC#の場合はメソッドですね!)のオーバーロードです。「メソッドの名前と引数をメソッドのシグニチャ」という、とのことでシグニチャが 異なればオーバーロード(同じ名前のメソッドを持つこと...それってなんかかぶっている感じがしますが)可能とのこと。戻り値はどうなの?と思いましたが、Microsoftによれば「アクセス レベル、オプションの修飾子、戻り値、メソッドの名前、およびメソッド パラメーター」「のまとまりがメソッドのシグネチャ」なんですが、「メソッドのオーバーロードを可能にするために、メソッドの戻り値の型はメソッドのシグネチャには含まれません」とのことです。

 

今日も短いサンプルをつなぎ合わせて、↓のようにしてみました。

// overload01-02.cs
using System;
class Sq
{
    public static int sq(int x)
    {
        Console.WriteLine("intバージョンが呼ばれました");
        return x * x;
    }
    public static double sq(double x)
    {
        Console.WriteLine("doubleバージョンが呼ばれました");
        return x * x;
    }
    public static string sq(int x, ref string str)    //これは戻り値の違いがシグニチュァになるかテストし、ダメだったので、台2引数を追加したものです。
    {
        Console.WriteLine("stringバージョンが呼ばれました");
        str = (x * x).ToString();
        return str;
    }
}

class Plus
{
    public int m_x {get; set;}    //使いませんでしたが、為念コンパイラーが通るか試してみました。しかし、"public int m_x {get; set;} = 0;"という初期化はエラーになりますね。

    public int add(int x)
    {
        m_x += x;
        return m_x;
    }

    public int add(int x, int y)
    {
        m_x += x + y;
        return m_x;
    }

    public int add(int x, int y, int z)
    {
        m_x += x + y + z;
        return m_x;
    }

    public void Show()
    {
        Console.WriteLine("m_xの値は{0}です。", m_x);
    }
}

class Sample
{
    public static void Main()
    {
        // overload01
        Console.WriteLine("{0}の2乗は{1}です", 5, Sq.sq(5));
        Console.WriteLine("{0}の2乗は{1}です", 0.5, Sq.sq(0.5));
        string str = "";    //string str;だけだと「未割り当てのローカル変数 'str' が使用されました。」エラーとなる。
        Console.WriteLine("{0}の2乗は{1}です", 10, Sq.sq(10, ref str));
        // overload02
        Plus plus = new Plus();
        plus.Show();
        Console.WriteLine("m_x += {0}", 10);
        plus.add(10);
        plus.Show();
        Console.WriteLine("m_x += {0} + {1}", 10, 20);
        plus.add(10, 20);
        plus.Show();
        Console.WriteLine("m_x += {0} + {1} + {2}", 10, 20, 30);
        plus.add(10, 20, 30);
        plus.Show();
        Console.ReadKey();
    }
}

 

未だ慣れていないので、時々「(メモリー)未割り当てのローカル変数 'str' が使用されました。」エラーを出します。しかし、慣れすぎてnewを使っても、deleteしない環境にはなれましたがね。(笑)