C函数重载的替代方法 [英] Alternatives to function overloading in C

查看:70
本文介绍了C函数重载的替代方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找一种避免重写函数的优雅方法,该函数的实现几乎相同,但是只有签名(输入参数及其数据类型的数量)不同.我知道在C语言中不可能实现函数重载.我也知道可变参数函数的存在.但是我认为他们在这种情况下不会有帮助.

I'm looking for an elegant way to avoid re-writing a function, whose implementation is almost the same, but only the signature (the number of input parameters and their data types) is different. I know function overloading is not possible in C. I also know about the existence of variadic functions. But I think they won't be helpful in this situation.

考虑以下问题,我们需要计算三角形的面积.我们有两个函数实现两个不同的公式:S = 1/2bh和S = sqrt(s(s-a)(s-b)(s-c)).除了计算面积之外,每个功能还修改了参数nbnthr.最后,有一个顶级例程bisect_area_...在给定函数area_tria1area_tria2上启动二等分过程,以针对参数nbnthr对其进行优化.目前,我明确实现了两个等分函数:一个用于area_tria1的签名,另一个用于area_tria2的签名.我觉得必须有一种更好,更优雅的方法,该方法允许有一个通用的二等分函数bisect_area_tria().请注意,实际上,我手边的输入参数数据类型也不同.

Consider the following problem, where we need to calculate the area of a triangle. We have two functions implementing two different formulae: S = 1/2bh and S = sqrt(s(s-a)(s-b)(s-c)). Apart from calculating the area each of the functions also modifies a parameter nb or nthr. Finally, there is a top level routine bisect_area_... that launches a bisection procedure on a given function area_tria1 or area_tria2 optimising it for a parameter nb or nthr. Currently I explicitly implement two bisection functions: one for the signature of area_tria1 and another one for area_tria2. I feel there must be a better, more elegant way, that would allow to have a single generic bisection function bisect_area_tria(). Please note, in the real case, that I have at hand, the input parameter data types also differ.

下面是函数签名的基本伪代码:

Below is a skeleton pseudocode of the function signatures:

// Calculate area of triangle, modify and return parameter 'nb'
void area_tria1_nb(..., int *nb, double b, double h, double *S) {

    // change parameter 'nb'
    ...

    S = 0.5*b*h;
}

// Calculate area of triangle, modify and return parameter 'nthr'
void area_tria1_nthr(..., int *nthr, double b, double h, double *S) {

    // change parameter 'nthr'
    ...

    S = 0.5*b*h;
}

// Optimise calculation of area of triangle, for parameter 'nb' or 'nthr'
void bisect_area_tria1(..., double b, double h, double *S, int (*area_tria1)(double, double)) {
}

// Calculate area of triangle, modify and return parameter 'nb'
void area_tria2_nb(..., int *nb, double a, double b, double c, double *S) {

    // change parameter 'nb'
    ...

    S = sqrt(s*(s-a)*(s-b)*(s-c));
}


// Calculate area of triangle, modify and return parameter 'nthr'
void area_tria_2_nthr(..., int *nthr, double a, double b, double c, double *S) {

    // change parameter 'nthr'
    ...

    S = sqrt(s*(s-a)*(s-b)*(s-c));
}


// Optimise calculation of area of triangle, for parameter 'nb' or 'nthr'
void bisect_area_tria2(..., double a, double b, double c, double *S, int (*area_tria2)(double, double, double)) {
}

void main() {

    bisect_area_tria1(..., &nb,   b, h, &S, area_tria1_nb);
    bisect_area_tria1(..., &nthr, b, h, &S, area_tria1_nthr);

    bisect_area_tria2(..., &nb,   a, b, c, &S, area_tria2_nb);
    bisect_area_tria2(..., &nthr, a, b, c, &S, area_tria2_nthr);

}

推荐答案

简单而又简单的方法:

#include <stdio.h>

void func_int (int x) { printf("%d\n", x); }
void func_char (char ch) { printf("%c\n", ch); }

#define func(param)          \
  _Generic((param),          \
    int:  func_int(param),   \
    char: func_char(param)); \

int main() 
{
  func(1);
  func((char){'A'});
}

这是类型安全的,但仅支持一个参数.乍一看似乎还不够.

This is type safe but only supports one parameter. At a glance this might seem insufficient.

如果要使用完全可变的参数列表,则必须实现一种解析可变参数宏和__VA_ARGS__的方法.可能的话.可能是丑陋的.可能,这不是您所需要的.

If you want completely variable parameter lists, then you'd have to implement a way to parse variadic macros and __VA_ARGS__. Likely, it is possible. Likely it is ugly. Likely, this is not what you need.

通常,对函数重载的需求可能是"XY问题".您需要具有带有不同参数集的函数,并且确信函数重载是解决它的最佳方法.因此,您会问如何在C中执行函数重载.事实证明,这不一定是最好的方法.

The need for function overloading in general might be "an XY problem". You need to have functions with different parameter sets and you are convinced that function overloading is the best way to solve it. Therefore you ask how to do function overloading in C. Which is, as it turns out, not necessarily the best way.

更好的方法是使用单个struct参数创建一个函数接口,该结构参数可以修改为包含所有必需的参数.通过这样的界面,您可以使用基于_Generic的上述简单方法.输入安全且可维护的内容.

A much better way would be to make a function interface with a single struct parameter, which can be adapted to contain all the necessary parameters. With such an interface you can use the above simple method based on _Generic. Type safe and maintainable.

这篇关于C函数重载的替代方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆