函数的模糊引用/值版本
Ambiguous Reference/Value Versions of Functions
考虑以下函数原型:
void Remove(SomeContainer& Vec, const std::size_t Index);
SomeContainer Remove(SomeContainer Vec, const std::size_t Index);
第二个是根据第一个实现的。也就是说,除了一个是按引用传递,另一个是按值传递之外,它们在各方面都是功能相同的。
然而,GCC说在这种情况下这些是不明确的,即使第一种形式是唯一不返回值的:
Remove(SomeContainer, 123);
是否有任何解决这个问题的方法,或者我是否必须为每个表单提出不同的名称?
返回类型不是函数重载的基础。
函数的重载只能满足以下条件之一:
- 参数个数
- 参数类型&
- 参数序列
返回类型可以被调用者忽略,因此它不是函数重载的有效标准。
如上所述,按值传递和传递引用会给编译器造成歧义。如:
void doSomething(int i)
{
}
void doSomething(int &i)
{
}
int main()
{
int val = 10;
doSomething(val); //Ambiguous
}
这里编译器不能确定将val
传递给哪个版本的doSomething()
。它可以对任何版本进行有效的函数调用,因此它会在编译时请求帮助(因为这是静态链接),并将调用标记为二义性。
如果像你这样。重命名函数或传递指针参数将使两个函数重载(名称相同但参数类型不同)是一种选择/偏好。然而,考虑到需求是很重要的。函数在选择首选项时将要执行的动作。就我个人而言,我不会仅仅为了重载而选择指针。如果我确实需要重置或使我的参数指向不同的变量,那么选择指针参数是有意义的。
简单的方法是只使用两个不同的函数名。它没有开销,而且和其他函数调用一样高效。
如前所述,返回类型不考虑重载。然而,编译器确实会考虑纯值和引用不同的类型,但它通常不知道调用哪个版本。换句话说,两个重载函数的不同之处在于参数是按值传递还是按引用传递,直到您尝试调用它时才会出现问题:在c++中,潜在的歧义不是错误。
的例子:
void f(int) {
cout << "valuen";
}
void f(int&) {
cout << "referencen";
}
int main() {
int val = 42;
f(val); // Error! Ambiguous.
f(static_cast<int>(val)); // OK: The type is int. Will print "value"
}
我不知道如何表示你想要f(int&)
,但是,所以在这方面没有太多的实际用途-我只是想澄清c++重载是如何工作的。
您可以通过选择更有区别的名称来帮助编译器和函数的用户:
Container Removed( const Container& c, size_t index );
void Remove( Container& c, size_t index );
将const
添加到不可变版本还将阻止用户意外调用命令式变体(编译器不允许,至少对const
容器不允许)。
按引用/值传递不用于确定函数重载,因为编译器无法知道哪个是必需的——对于作为参数传递的值,两者都是同样好的匹配。而且正如其他人指出的那样,从来没有考虑过返回类型。
- 将对象数组的引用传递给函数
- 什么时候在C++中返回常量引用是个好主意
- 我想将一个对T类型的非常量左值引用绑定到一个T类型的临时值
- 为cl.exe(Visual Studio代码)指定命令行C++版本
- 何时在引用或唯一指针上使用移动语义
- 如何在c++中使用引用实现类似python的行为
- 导入库可以跨dll版本工作吗
- 编译C++时未定义的引用
- Ctypes wstring通过引用传递
- c++r值引用应用于函数指针
- 理解c++中的引用
- C++取消引用指针.为什么会发生变化
- 当使用CreateObject从VBScript引用DLL时C++如何处理DLL版本?
- 不同编译器版本的C++中的奇怪行为(字符串通过引用传递):参见简单的程序说明
- C++ "错误:"引用中缺少对象..."取决于 GCC 版本
- 更新版本化的 .NET 程序集引用
- 当 Gcc 编译具有多个版本的 boost 的 Boost::regex 时,未定义的引用
- 最新SDL 2.0版本中未定义的引用
- GCC报告基于版本库的未引用符号
- 函数的模糊引用/值版本