多重定義
出典: フリー百科事典『ウィキペディア(Wikipedia)』
多重定義(たじゅうていぎ)とは、プログラミング言語において関数や演算子やメソッドの同一名や同一の演算子記号について複数定義し、利用時にプログラムの文脈に応じて選択することで複数の動作を行わせる仕組みである。 例えば整数型や実数型、複素数型の値について同じ"+"演算子を使って加算を行う、クラスごとに個々の意味で名前やIDを返すメソッドを定義するなどが挙げられる。英語表記そのままにオーバーローディングあるいはオーバーロードと呼ばれることもあり、多重定義する対象に応じてそれぞれ関数オーバーローディング (function overloading)、演算子オーバーローディング (operator overloading)、メソッド・オーバーローディング (method overloding) と呼ばれる。
動作を選択する際に用いられる代表的な文脈情報としては、型付けられたプログラミング言語においては関数や演算子に実引数(演算子ならばオペランド)として与えられた式や変数に関連付けられた型の情報が用いられる(稀ではあるが返り値の型を利用できるプログラミング言語も存在する)。関数の名称とそれらの型情報の組を合わせたものをシグネチャと呼ぶが、プログラム内でシグネチャが唯一に決まれば、関数名やメソッド名、演算子の記号が重複していても呼び出すべき対象を唯一に決定することが出来る。 このような型づけによる多重定義は、暗黙の型変換(implicit type conversion あるいは 型強制 (type coercion))、継承(inheritance あるいは包含(inclusion))、総称型(generic type、あるいはパラメタ付型(parametric type))と並んでプログラミング言語において多相型 (polymorphic type) を実現するための一つの手段であるとみなせる。
理論的には関数の名前や演算子記号は単なる記号であり、意味的必然があるわけではないので、これを反映して多重定義を許すプログラミング言語では多重定義された関数や演算子、メソッドの意味や動作の定義はかなり自由に行うことが出来る(演算子については構文解析の都合上、優先順位などが制限される場合も有る)。とはいえ関数名やメソッド、特に演算子の用法には各分野及びプログラミング言語毎に慣習が育っている場合があり、著名な関数(例えば数学関数のsin()など)やメソッド、演算子に対して慣習とあまりにかけ離れた意味、即ち動作の定義を与えるとプログラムの可読性の著しい低下をもたらす可能性があるので注意が必要である。
例えば、C++において何らかの数値型例えば有理数型のためのクラスを定義するとして、その際+演算子を加算以外の意味で定義すれば間違いなく混乱するであろう。 一方意味が大きく変わる場合でも比較的安全な事例もある。例えば、C++において整数型に対する<<は左ビットシフト演算を意味するが、C++の標準入出力ライブラリで提供されるストリーム型(入出力列を抽象化した型)については右オペランドの値を左オペランドのストリームに書き込むことを意味する。これは一見混乱するようにも見えるが、整数シフトという意味づけはCから引き継いだ以外には特に数学的背景などの慣習もなく、プログラミングにおいて整数型とストリーム型を混同することも考えにくいため比較的無難な多重定義と言える。
boostの提供するライブラリに至っては、より前衛的な多重定義が行われている。各種演算子が悉く異なる意味で用いられたり、本来配列の添え字を表現するための演算子であった[]を、数式上の括弧の一種であるかのように扱っていたりするケースがある。こうして、本来のプログラム言語の構造から離れた独自の文法をもたせて高度なプログラミングを行うことができるのも多重定義の特徴であるが、このようなスタイルには賛否もある。