コンピュータプログラミングにおいて、関数プロトタイプ とは、関数の名前と型シグネチャ(引数の数、パラメータのデータ型、戻り値の型)を指定する関数の宣言であり、関数本体は省略されます。関数定義は関数がどのように動作するか(「実装」)を指定しますが、関数プロトタイプは単にインターフェース、つまりどのようなデータ型が入力および出力されるかを指定します。「関数プロトタイプ」という用語は、特にプログラミング言語CおよびC++の文脈で使用されます。これらの言語では、ヘッダーファイルに関数の前方宣言を配置することで、プログラムを翻訳単位、つまりコンパイラが個別にオブジェクトファイルに変換できる部分に分割し、リンカによって実行可能ファイルまたはライブラリに結合することができます。関数宣言は関数定義の前にあり、名前、戻り値の型、ストレージクラス、およびその他の関連属性の詳細を示します。[ 1 ]
関数プロトタイプは、以下のいずれかの場合に使用できます。[ 2 ]
プロトタイプでは、パラメータ名は省略可能ですが(C/C++では関数プロトタイプスコープを持ち、そのスコープはプロトタイプの終わりで終了します)、型はすべての修飾子とともに必要です(たとえば、ポインタまたはconstパラメータへの参照である場合など)。ただし、const単独の場合は例外です。
オブジェクト指向プログラミングにおいて、インターフェースと抽象メソッドはほぼ同じ目的を果たす。
次の関数プロトタイプを考えてみましょう。
void sum ( int a , int b );// 名前付きパラメータなし: void sum ( int , int );// 末尾の戻り値型 (C++): auto sum ( int , int ) -> void ;関数プロトタイプには、関数シグネチャ、関数名、戻り値の型、およびアクセス指定子が含まれます。この例では、関数名は「sum」です。関数シグネチャは、パラメータの数とその型を定義します。戻り値の型は「void」です。これは、関数が値を返さないことを意味します。最初の例のパラメータ名は省略可能であることに注意してください。
C言語の初期バージョンでは、関数が事前に宣言されておらず、その関数名が左括弧の後に続く式の中に現れた場合、その関数は暗黙的に戻り値を返す関数として宣言されint、引数については何も想定されていませんでした。この場合、コンパイラは引数の数と型のコンパイル時妥当性チェックを実行できませんでした。C99規格ではプロトタイプの使用が義務付けられています。
#include <limits.h> #include <stdio.h>// 関数プロトタイプchar orderingCharacter ( int n );int main () { putchar ( orderingCharacter ( -1 )); // 正しくフォーマットされた呼び出しputchar ( orderingCharacter ( 1.5 )); // コンパイラ警告: 型の不一致putchar ( orderingCharacter ( "Hello" )); // コンパイラ警告: 型の不一致putchar ( orderingCharacter ()); // コンパイラエラー: 引数が少なすぎます// INT_MAXに1を加えると整数オーバーフローエラーになりますが、// コンパイル時には検出できません。putchar ( orderingCharacter ( INT_MAX + 1 )); }// 関数定義char orderingCharacter ( int n ) { if ( n > 0 ) { return '>' ; } else if ( n < 0 ) { return '<' ; } return '=' ; }この関数はorderingCharacter()整数型の引数で呼び出されることを想定しています。関数プロトタイプを含めることで、コンパイラにこの関数が1つの整数型の引数を取ることを伝え、誤った呼び出しをコンパイラが検出できるようにします。
関数プロトタイプをヘッダーファイルに配置することで、ライブラリのインターフェースを指定できます。
C++では、関数プロトタイプはクラス定義でも使用されます。
JavaとC#では、インターフェースはシグネチャで宣言され、その後、実装クラスによって実装されます。
interface PaymentProcessor { boolean processPayment ( double amount , String currency ); String getReceiptDetails (); void refundPayment ( String transactionId ); }class CreditCardProcessor implements PaymentProcessor { private double lastAmount ; private String lastTransactionId ;@Override public boolean processPayment ( double amount , String currency ) { this.lastAmount = amount ; this.lastTransactionId = " TXN" + System.currentTimeMillis ( ); System.out.printf ( " Processing credit card payment of %f % s ... % n " , amount , currency ) ; return true ; }@Override public String getReceiptDetails () { return String.format ( "ID % sの領収書| 金額: $%f" , lastTransactionId , lastAmount ); }@Override public void refundPayment ( String transactionId ) { System . out . printf ( "Refunding transaction: %s...%n" , transactionId ); } }