首页 > 解决方案 > 您可以在 C 中进行重载并具有相同的函数名吗?

问题描述

在 Java 中,当方法具有相同名称时,我们可以进行重载。我在谷歌上搜索,它说 C 不支持重载,所以我想知道有没有办法在 C 中做类似于重载的事情。

例如:

int max(int num1, int num2);
double max(double num1, num2);

int main(){
  printf(...);
  printf(...);
}

int max(int num1, int num2){
  ...
}

double max(double num1, double num2){
  ...
}

标签: coverloading

解决方案


您找到的参考是正确的:C 不支持重载,因此。

它所拥有的(假设我们谈论的是实际的 C 而不是历史版本)是一个通用选择器,它允许您编写自己的宏来进行动态调度。

C99 引入了tgmath.h标头,它允许重载某些数学函数以使用不同宽度的浮点参数,在某些情况下还可以使用复杂的参数。但是,C99 中没有引入任何工具来允许将该功能推广到其他功能。C11 中引入的通用选择器就是该工具。

选择器的格式为_Generic(select-expression, type-associations),其中type-associations包含以逗号分隔的格式对列表type : expression。选择器将被替换为与 的类型对应的表达式select-expression。s之一type可以是关键字default;其他的必须是唯一的完整类型(即列表中没有两种类型可以兼容)[注1]。需要注意的是,关联列表中的所有表达式都必须正确编译,而不仅仅是最终选择的那个。通常,表达式将是函数指针,而不是函数调用。

一个例子可能会更清楚地说明这一点。假设我们有两个函数(名称不同,所以这不是名称重载):

int max_int(int a, int b) { return a > b ? a : b; }
double max_dbl(double a, double b) { return a > b ? a : b; }

现在,我们可以定义宏 MAX:

#define MAX(a, b) _Generic((a)+(b),          \
                    int : max_int,           \
                    double : max_dbl)(a, b)

在这里,我将a+b其用作选择器表达式而不是a,因为 ofa+b的类型是由通常的算术转换产生的类型。如果我刚刚使用a,那么MAX(3, 5.7)会产生一个意想不到的结果,因为通用选择器会被选中max_int并且5.7会被默默地截断为 5。使用a+b,选择器的类型将是double,导致调用max_dbl,这两个值都是转换为双倍。

我可以(a)+(b)在宏中使用,因为_Generic不评估选择器表达式(如sizeof)。因此,不存在对具有副作用的论点进行双重评估的危险。


笔记:

  1. 通用关联的类型不能是 VLA(可变长度数组),即使编译器实现了它们。但是任何其他完整类型都可以,即使是指向不完整类型的指针。

推荐阅读