Root One

数学中心のブログです。

すべてはmain関数から始まる(と思っていた話)

最近数学から離れていて、C++の話が中心になっています. 今回もC++です.
早速本題に入っていきます。

main関数は「はじめに実行される」と教わったような...

おそらく、プログラムを勉強するときに最初に作成するのが
Hello World
を表示するプログラムだと思います。c++だと次のような感じになります。

#include <iostream>
using namespace std;
int main()
{
    cout << "Hello World\n";
}

実行結果.

Hello World

このようなプログラムとほぼ同時に、
main関数というのは最初に実行されるもの
と教わることが多いのではないかと思います。
しかし、先日、mainの外部にクラスのインスタンスを作れば、コンストラクタがその前に
実行されるということを知りました。
つまり、mainが最初に実行される関数とは限らないということになります。
それどころか、コンストラクタでexitしてしまえば、mainに到達する前にプログラムを終了させることも可能です。

#include <iostream>
using namespace std;
class MAIN {
public:
    MAIN() {
        cout << "My MAIN Hello!" << endl;
        exit(0);
    }
};
MAIN m;  // コンストラクタがよばれる

int main()
{
    cout << "本当のメイン関数\n";
}

実行結果.

My MAIN Hello!

実行結果を見るとわかるのですが、mainのcoutが実行されていません。つまり、main関数実行前にプログラムは終了していることになります。
だから何だという話がありますが、
一つのメリットとしては、プロトタイプ宣言しなくても関数をMAINの後ろに置くことができるという点でしょうか。
例えば、「MAIN」関数の前にgcdを定義して次のように書いたとします。

#include <iostream>
using namespace std;
class MAIN {
public:
    int gcd(int a, int b) {
        if (b == 0) {
            return abs(a);
        }
        return gcd(b, a % b);
    }
    MAIN() {
        int a = 15;
        int b = 20;
        cout << "gcd(" <<a <<"," << b << ")=" <<  gcd(a,b) << endl;
        exit(0);
    }
};
MAIN m; // コンストラクタがよばれる

int main()
{
    cout << "本当のメイン関数\n";
}

実行結果.

gcd(15,20)=5

これは問題なく実行されるわけですが、gcdの位置をMAINの後ろに持ってくることもできます。

#include <iostream>
using namespace std;
class MAIN {
public:
    MAIN() {
        int a = 15;
        int b = 20;
        cout << "gcd(" <<a <<"," << b << ")=" <<  gcd(a,b) << endl;
        exit(0);
    }
    int gcd(int a, int b) {
        if (b == 0) {
            return abs(a);
        }
        return gcd(b, a % b);
    }
};
MAIN m;

int main()
{
    cout << "本当のメイン関数\n";
}

実行結果.

gcd(15,20)=5

もちろん、このような書き方を推奨したいわけではありません。一応メリットもないわけではないというお話です。
他にもメリットはありそうですが、それは一旦置いておいて、
今回の記事を要約すると「main関数の前に実行される関数を作ることができる」ということになります。