【C言語】第5章第11回:関数のオーバーロード(C言語での疑似的な実現)
関数のオーバーロードは、異なる引数を持つ複数の関数を同じ名前で定義する手法です。C++ではサポートされていますが、C言語では直接のサポートがありません。この章では、C言語で関数のオーバーロードを疑似的に実現する方法を解説します。
1. 関数のオーバーロードとは?
1.1 オーバーロードの概要
オーバーロードとは、関数名を同じにしながら、異なる引数リストを持つ関数を複数定義する技法です。
1.2 C言語での制約
C言語では関数のシグネチャ(関数名+引数の型)が一致する場合、同名の関数を複数定義することはできません。そのため、疑似的な方法を用いる必要があります。
2. 疑似的なオーバーロードの実現方法
2.1 可変引数を使用する方法
例:整数の加算を行う関数
#include <stdio.h>
#include <stdarg.h>
// 可変引数を使用した関数
int add(int count, ...) {
va_list args;
va_start(args, count);
int sum = 0;
for (int i = 0; i < count; i++) {
sum += va_arg(args, int);
}
va_end(args);
return sum;
}
int main() {
printf("Sum of 2, 3: %d\n", add(2, 2, 3));
printf("Sum of 1, 4, 5: %d\n", add(3, 1, 4, 5));
return 0;
}
解説:
va_list
を使って可変引数を管理します。va_start
とva_end
で引数のリストを初期化・終了します。va_arg
で引数を順に取得します。
2.2 マクロを使用する方法
例:マクロで異なる関数を呼び出す
#include <stdio.h>
// 関数プロトタイプ
void printInt(int num);
void printDouble(double num);
// マクロで関数を切り替え
#define PRINT(x) _Generic((x), \
int: printInt, \
double: printDouble)(x)
// 関数の実装
void printInt(int num) {
printf("Integer: %d\n", num);
}
void printDouble(double num) {
printf("Double: %.2f\n", num);
}
int main() {
PRINT(10); // 整数
PRINT(3.14); // 浮動小数点数
return 0;
}
解説:
_Generic
を使って、引数の型に応じた関数を呼び出します。- 型に依存した処理を柔軟に実現できます。
3. 応用例:異なる型のデータを出力する関数
3.1 プログラム例
#include <stdio.h>
// 関数プロトタイプ
void printData(int type, void *data);
// 定数でデータ型を指定
#define TYPE_INT 1
#define TYPE_DOUBLE 2
void printData(int type, void *data) {
switch (type) {
case TYPE_INT:
printf("Integer: %d\n", *(int *)data);
break;
case TYPE_DOUBLE:
printf("Double: %.2f\n", *(double *)data);
break;
default:
printf("Unknown type\n");
}
}
int main() {
int num = 42;
double pi = 3.14159;
printData(TYPE_INT, &num);
printData(TYPE_DOUBLE, &pi);
return 0;
}
解説:
void *
型を使用して汎用的なデータを渡します。switch
文でデータ型を判定し、適切な処理を行います。
4. 練習問題
以下の課題に挑戦して、関数の疑似的なオーバーロードを試してみましょう。
- 可変引数を使って、複数の浮動小数点数の平均を計算する関数を作成してください。
- マクロを使用して、文字列と整数を別々に出力するプログラムを作成してください。
void *
型を使用して、異なる型のデータを処理する汎用関数を作成してください。
5. 練習問題の解答と解説
問1の解答
#include <stdio.h>
#include <stdarg.h>
double calculateAverage(int count, ...) {
va_list args;
va_start(args, count);
double sum = 0.0;
for (int i = 0; i < count; i++) {
sum += va_arg(args, double);
}
va_end(args);
return sum / count;
}
int main() {
printf("Average: %.2f\n", calculateAverage(3, 1.5, 2.5, 3.5));
return 0;
}
6. まとめ
C言語では関数のオーバーロードを直接サポートしていませんが、可変引数やマクロを使って疑似的に実現できます。次回は、関数テンプレートの概念について学びます。