这个C ++问题似乎非常基础和一般,但我仍然希望有人回答。
1)具有可变长度参数的函数和重载函数之间有什么区别? 2)如果我们有一个带有可变长度参数的函数和另一个具有相似参数的同名函数,我们会遇到问题吗?
答案 0 :(得分:7)
2)你的意思是以下几点吗?
int mul(int a, int b);
int mul(int n, ...);
假设第一个乘以2个整数。第二个乘以var-args传递的n
个整数。用f(1, 2)
调用不会有歧义,因为通过“省略号”传递的参数与可能的最高成本相关联。但是,将参数传递给相同类型的参数会与可能的最低成本相关联。所以这个电话肯定会被解决到第一个功能:)
请注意,重载决策仅将参数与同一位置的参数转换进行比较。如果某个参数对的任一函数都有赢家,它将会很难。例如
int mul(int a, int b);
int mul(double a, ...);
想象一下,第一个乘以两个整数,第二个乘以由0.0
终止的双精度列表。这个重载集是有缺陷的,并且在被
mul(3.14, 0.0);
这是因为第二个函数在第一个参数中获胜,但第一个函数在第二个参数中获胜。第二个参数的转换成本对于第二个函数而言要高于第一个函数的第一个参数的成本并不重要。一旦确定了这种“交叉”赢家的情况,对这两个候选人的要求就不明确了。
答案 1 :(得分:1)
1)好的重载函数需要很多不同原型和实现的HELL。它也是类型安全的 2)是的,这会导致问题,因为编译器不知道它需要调用哪个函数。它可能会也可能不会对此发出警告。如果不是,你最终可能很难找到错误。
答案 2 :(得分:1)
重载函数可以具有完全不同的参数类型,包括无参数类型,根据参数类型选择正确的参数类型。
可变长度参数要求至少存在一个参数。您还需要一些机制来“预测”下一个参数的类型(因为您必须在va_arg()
中说明它),并且它必须是基本类型(即整数,浮点或指针)。这里的常用技术是“格式字符串”(如printf()
,scanf()
)或“标记列表”(参数列表中的每个奇数元素都是一个枚举,告诉以下偶数元素的类型,零枚举以标记参数列表的结尾。)
一般来说,重载是C ++的方法。如果您最终需要类似于C ++中的可变长度参数列表,例如为了方便地链接各种数量和类型的参数,请考虑C ++流如何工作(那些连接“<<”和“>>”s):
class MyClass {
public:
MyClass & operator<<( int i )
{
// do something with integer
return *this;
}
MyClass & operator<<( double d )
{
// do something with float
return *this;
}
};
int main()
{
MyClass foo;
foo << 42 << 3.14 << 0.1234 << 23;
return 0;
}
答案 3 :(得分:0)
这很普遍,Goz已经涵盖了一些观点。还有一些:
1)如果传递除POD对象之外的任何内容,则变量参数列表会给出未定义的行为。重载函数可以接收任何类型的对象。
2)如果重载集的一个成员采用变量参数列表,则可能存在歧义。再说一次,如果没有这个,你可能会有歧义。但是,变量参数列表可能会在更多情况下产生歧义。
第一点是非常严重的一点 - 对于大多数实际用途,它将变量参数列表纯粹呈现为C ++中的“遗留”项,甚至不考虑在任何新代码中使用。最常见的替代方法是链接重载运算符(例如iostream插入器/提取器与printf / scanf)。