多重 定義
概要
[sin
など)やメソッド、
デフォルト
言語 による多重 定義 のサポート
[C
#include <stdio.h>
#include <math.h>
float vector2f_length(float x, float y) { return sqrtf(x * x + y * y); }
double vector2d_length(double x, double y) { return sqrt(x * x + y * y); }
float vector3f_length(float x, float y, float z) { return sqrtf(x * x + y * y + z * z); }
double vector3d_length(double x, double y, float z) { return sqrt(x * x + y * y + z * z); }
int main(void)
{
printf("%f\n", vector2f_length(1.0f, -1.0f));
printf("%f\n", vector2d_length(1.0, 2.0));
printf("%f\n", vector3f_length(1.0f, -1.0f, 1.0f));
printf("%f\n", vector3d_length(1.0, 2.0, -1.0));
}
ベクトルの
C++での
#include <cstdio>
#include <cmath>
float vector_length(float x, float y) { return std::sqrt(x * x + y * y); }
double vector_length(double x, double y) { return std::sqrt(x * x + y * y); }
float vector_length(float x, float y, float z) { return std::sqrt(x * x + y * y + z * z); }
double vector_length(double x, double y, float z) { return std::sqrt(x * x + y * y + z * z); }
int main(void)
{
printf("%f\n", vector_length(1.0f, -1.0f)); // (float, float) バージョンが呼 ばれる。
printf("%f\n", vector_length(1.0, 2.0)); // (double, double) バージョンが呼 ばれる。
printf("%f\n", vector_length(1.0f, -1.0f, 1.0f)); // (float, float, float) バージョンが呼 ばれる。
printf("%f\n", vector_length(1.0, 2.0, -1.0)); // (double, double, double) バージョンが呼 ばれる。
}
なお、C++11std::hypot()
ルックアップ
[java.lang.String
クラスはjava.lang.Object
クラスからtestMethod()
は
public class Main {
static void testMethod(String str) { System.out.println("String version is called."); }
static void testMethod(Object obj) { System.out.println("Object version is called."); }
public static void main(String[] args) {
String str = "test";
Object obj = str;
testMethod(str); // String バージョンが呼 ばれる。
testMethod(obj); // Object バージョンが呼 ばれる。
}
}
なお、
printf("%f\n", vector_length(1, -1)); // コンパイルエラー。
printf("%f\n", vector_length(1.0f, -1.0)); // コンパイルエラー。
printf("%f\n", vector_length(1.0, -1.0f)); // コンパイルエラー。
printf("%f\n", vector_length(double(1), double(-1))); // コンパイル可能 。(double, double) バージョンが呼 ばれる。
printf("%f\n", vector2d_length(1, -1)); /* コンパイル可能 。 */
printf("%f\n", vector2d_length(1.0f, -1.0)); /* コンパイル可能 。 */
printf("%f\n", vector2d_length(1.0, -1.0f)); /* コンパイル可能 。 */
欠点
[多重 定義 の例
[// (1-1): 引数 の数 の違 いによる多重 定義
int Function(void);
int Function( int value );
int Function( int value0, int value1 );
// (2): 引数 の修飾 子 の違 いによる多重 定義
int Function( int *value );
int Function( int const *value );
int Function( int *const *value );
int Function( int *const *const *value );
// (3): 引数 の型 の違 いによる多重 定義
int Function( char value );
int Function( std::complex< double > const &value );
int Function( ... ); // ※1
template< class Type > int Function( Type const &value ); // ※2
struct Example
{
// (1-2): 引数 の型 の違 いによる多重 定義 (コンストラクター版 )
Example(void);
Example( int value );
// (4): メンバー関数 の修飾 子 の違 いによる多重 定義
int Function(void);
int Function(void) const;
// (1-3): 引数 の型 の違 いによる多重 定義 (メンバー関数 版 )
int Function( int value );
// (5): 戻 り値 の型 の違 いによる多重 定義
operator bool (void) const;
operator int (void) const;
};
module Example
implicit none
! Function0, Function1をFunctionとして定義 。FORTRANに予約 語 はなくFunctionは予約 語 ではない。
interface Function
module procedure Function0, Function1
end interface Function
contains
function Function0( value1 ) result( value0 )
!省略
end function Function0
function Function1( value1, value2 ) result( value0 )
!省略
end function Function1
end module Example
演算 子 の多重 定義
[オブジェクト
テンプレートと多重 定義
[C++の
#include <cmath>
#include <cstdlib>
// 引数 valueの符号 に応 じて、-1, 1または0を返 す関数 。
// ※absを使用 しているため、引数 に指定 できる値 の値 の範囲 はこの関数 の引数 と同 じ型 (反 変 な型 )をとるabsの仕様 に依存 する。
template<class Type> Type Sign( Type const &value )
{
return Type() == value ? Type() : abs( value ) / value; // 除算 演算 子 及 び、abs関数 の実体 はSignの引数 によって変 わる
}
int main(void)
{
double value = -2;
std::valarray<double> array( 2 );
double value_sign = Sign( value ); // double型 の-1, 1または0が返 る
std::valarray<double> array_sign = Sign( array ); // -1, 1または0を含 むvalarrayの値 が返 る
return EXIT_SUCCESS;
}
このstd::complex
に
この
まず、メンバー
なお
#include <cstdlib>
namespace Graphics
{
class Line { /* 省略 */ };
class Ellipse { /* 省略 */ };
class Square
{
/* 省略 */
Line At( size_t index ) const; // 四角形 の辺 を返 す関数
/* 省略 */
};
void Draw( ... )
{
}
// 四角形 を描画 する
template<class Type> void Draw( Type &device, Square const &shape )
{
Draw( device, shape.At( 0 ) );
Draw( device, shape.At( 1 ) );
Draw( device, shape.At( 2 ) );
Draw( device, shape.At( 3 ) );
}
}
namespace RasterDevice
{
struct Device { /* 省略 */ };
// Raster形式 用 に線分 を描画 する
void Draw( Device &device, Graphics::Line const &shape );
}
namespace VectorDevice
{
struct Device { /* 省略 */ };
// Vector形式 用 に線分 を描画 する
void Draw( Device &device, Graphics::Line const &shape );
}
namespace DisplayDevice
{
struct Device { /* 省略 */ };
// 表示 装置 用 に線分 を描画 する
void Draw( Device &device, Graphics::Line const &shape );
}
int main()
{
RasterDevice::Device device0;
VectorDevice::Device device1;
DisplayDevice::Device device2;
Draw( device0, Graphics::Square( 0, 0, 1, 1 ) ); // 内部 でRasterDevice::Draw( Device &, Graphics::Line const & )を呼 び出 す
Draw( device1, Graphics::Square( 0, 0, 1, 1 ) ); // 内部 でVectorDevice::Draw( Device &, Graphics::Line const & )を呼 び出 す
Draw( device1, Graphics::Square( 0, 0, 1, 1 ) ); // 内部 でDisplayDevice::Draw( Device &, Graphics::Line const & )を呼 び出 す
Draw( device0, Graphics::Ellipse( 0, 0, 1, 1 ) ); // Graphics::Draw( ... )を呼 び出 す
Draw( device1, Graphics::Ellipse( 0, 0, 1, 1 ) ); // Graphics::Draw( ... )を呼 び出 す
Draw( device2, Graphics::Ellipse( 0, 0, 1, 1 ) ); // Graphics::Draw( ... )を呼 び出 す
return EXIT_SUCCESS;
}
多重 定義 濫用 の弊害
[曖昧 な型 を持 つ言語
[PerlやPHPのような
また、PHPには「オーバーロード」という
脚注
[注釈
[出典
[- ^ std::hypot - cppreference.com
- ^ a b http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4296.pdf
- ^ http://www.j3-fortran.org/doc/year/10/10-007.pdf
- ^ “オーバーロード”.
言語 リファレンス. The PHP Group. 2014年 4月 16日 閲覧 。