C中的函数重载

Posted

技术标签:

【中文标题】C中的函数重载【英文标题】:Function overloading in C 【发布时间】:2011-02-10 18:31:06 【问题描述】:

今天,查看open() 的手册页,我注意到这个函数被“重载”了:

   int open(const char *pathname, int flags);
   int open(const char *pathname, int flags, mode_t mode);

我不认为这在 C 上是可能的。实现这一目标的“诀窍”是什么?

稍后编辑: 所以它并不是真正的重载,因为当使用可变参数时 - 你只能提供相同类型的多个参数。那么,mode_t 在幕后是 int 吗?

【问题讨论】:

mode_t 确实是一个整数,但您可以提供不同类型的参数,前提是您知道如何解释它们。 printf 系列函数就是这样做的,它使用格式字符串来知道如何解释它的额外参数,即使它们的类型不同。我在下面的回答有一些例子可以澄清这一点。 @Eli 谢谢,我一定把它和 Java 搞混了。 这样的函数称为可变参数函数。 【参考方案1】:

它正在使用variable arguments。这些声明仅出现在手册页中,因为这两种方法是您应该调用 open() 的唯一方法。实际的 C 函数将被声明为例如

int open(const char *pathname,int flags,...);

对于可变参数,参数不需要是相同的类型。 printf 就是一个明显的例子。

在 open() 的情况下,如果 'flags 包含 O_CREAT 标志,则第一个变量参数必须是 mode_t,因为 open() 的实现期望它是 mode_t(在幕后可能是 unsigned int 或unsigned long - 但这与可变参数无关)

【讨论】:

【参考方案2】:

C 确实可以使用variable number of argument 编写函数,例如printf

话虽如此,在 C 语言中没有可靠的、跨平台的方法来编写一个只需要 2 或 3 个参数的函数;一般来说,你必须做类似的事情

some_function(5, 6, 7, NULL);
some_function(5, 6, 8, 2, 5, NULL);

换句话说,你必须有一个终止的“sentinal”参数。或者,您可以以某种方式在较早的参数中包含参数的数量,例如

another_func(2, "hello", "world");
another_func(3, "goodbye", "cruel", "world");

printf 系列函数采用这种方法;第一个格式参数包含所需的额外参数的数量;例如printf("%f %f", 5.6, 7.11) 你知道必须有 2 个浮点参数。但是,这在用户定义的库函数中会有些不安全,因为如果您说my_printf("%s %f %f %f %s", 5.6),那么您可能会遇到段错误或更糟。幸运的是,大多数 C 编译器会在编译时检查您对 printf 的调用以避免此类问题。

open 的情况下,函数被声明为具有可变参数,并且仅当设置了O_CREAT 时才检查第三个参数。所以这就是它“安全地”确定是否存在第三个参数的方式。我将“安全”放在引号中,因为从技术上讲,open 无法在运行时知道实际传递了多少参数。例如,以下调用编译时不会出现任何错误或警告:

open("foo.txt", 5, "not an integer", 7);    // extra and invalid parameters
open("bar.txt", O_CREAT);                   // third parameter is missing

【讨论】:

如果some_function() 采用ints,则不应以NULL 结尾,因为NULL 在数字上下文中只是0。 NULL 终结符最适合使用指针参数。 @Chris:很好,我通常使用 NULL 作为终止符,而不管数据类型如何,但你说得对,它可能会让人感到困惑,尤其是对于那些不知道 0 和 NULL 是同样,因为他们可能认为他们可以编写类似 some_func(3, 2, 1, 0, -1, NULL) 的东西,而实际上这会导致 0 充当终止参数。 最新版本的 gcc 和 glibc 标头一起会对您的最后两个示例产生警告。【参考方案3】:

"当 O_CREAT 在标志中时必须指定模式,否则将被忽略。"

extern int open (__const char *__file, int __oflag, ...)

它使用varargs 并且仅在__oflag 包含O_CREAT 时加载模式变量参数。

【讨论】:

【参考方案4】:

非常简短的答案 - 可变参数

【讨论】:

并淘汰正确答案的反对票 - 简洁是一种美德。【参考方案5】:

你可以使用带有...的变量参数列表来伪造它

int function(int x, ...);

【讨论】:

以上是关于C中的函数重载的主要内容,如果未能解决你的问题,请参考以下文章

C中的函数重载

类中的函数重载

C++深度剖析学习总结 22 类中的函数重载

C++深度剖析学习总结 22 类中的函数重载

C ++中的复制构造函数和=运算符重载:通用函数可能吗?

5. 详解函数重载