c++重载返回void与非void
C++ overload return void vs. non-void
是否有什么特别的原因导致c++不允许基于返回值的重载?这样的:
void f(); //(1)
int f(); //(2)
int main(){
f(); // calls (1)
int x = f(); // calls (2)
return x;
}
只要忽略返回值,就调用void变量,因此重载解析不应该有任何问题。在标准库中也很有用,比如vector::pop_back()
。那为什么不允许呢?
Edit:已经注意到非void函数也可以在void上下文中调用。我知道这一点。我只是希望编译器更喜欢void函数,如果有一个。
这是一个语言规则,在c++编程语言第4版中,你可以阅读:
重载解析不考虑返回类型。原因是保持单个操作员的分辨率(§18.2.1,§18.2.5)或函数调用与上下文无关。
但是看看你的例子,它很清楚应该调用哪个函数:
f(); // calls (1)
int x = f(); // calls (2)
在(1)中为void版本,而在(2)中为非void版本。你可以在这个答案中阅读函数重载的返回类型?有些语言允许在返回类型上重载。
在c++中,你可以通过一些技巧来实现,比如转换操作符,问题是如何调用返回void类型的函数。下面是我解决这个问题的方法(或者说是滥用语言规则)。我不喜欢在析构函数中调用void版本——我认为不应该允许抛出它。无论如何,这只是为了好玩,我永远不会使用这样的代码。我已经在VS2005,g++4.8,clang(来自http://rextester.com/runcode -不确定哪个版本)上编译并运行了它。此外,我认为返回值优化将删除所有析构函数调用,但看起来它实际上并没有这样做。 http://coliru.stacked-crooked.com/a/6e052cc7c1bb56ca#include<iostream>
struct SomeClass {
int nonVoidFunc() {
std::cout << "nonVoidFunc()" << std::endl;
return 0;
}
void voidFunc() {
std::cout << "voidFunc()" << std::endl;
}
};
class Proxy {
SomeClass& sc;
bool callVoid;
Proxy(Proxy& p_sc) : sc(p_sc.sc), callVoid(false) { }
Proxy& operator=(const Proxy& pr) { return *this;}
public:
Proxy(SomeClass& p_sc) : sc(p_sc), callVoid(1) {}
~Proxy() {
if ( callVoid) sc.voidFunc();
}
template<typename T> operator T() {
callVoid = false;
return sc.nonVoidFunc();
}
public:
Proxy func() { return *this; }
};
int main() {
SomeClass sc;
Proxy p1(sc);
int n = p1.func(); // prints nonVoidFunc()
(void)n;
p1.func(); // prints voidFunc()
return 0;
}
返回非void类型的函数可以在忽略返回值的上下文中调用。例如,C函数printf()
的返回值类型为int
,但在实际中很少使用。
换句话说,您可以使用以下方式调用函数int f()
:
f();
返回值被忽略,只使用副作用
有。在c++或Java中,任何给定类中的方法都由方法签名识别,这里的签名定义为方法的名称以及方法接受的参数的类型和数量。返回类型不是方法签名的一部分,因此在这些编程语言中,重载的方法仅因返回类型不同是不可接受的。在你的例子: int x = f();
中,你假设用户将输入 int x
,但是程序员实际上并不需要这样做!在序言中,我解释了当用户调用 f()
时,编译器无法识别您是调用第一个还是第二个方法签名。也就是说,一些现代编程语言允许基于返回类型的重载。
不能重载仅返回类型不同的函数声明。
你的void f()
和int f()
的例子只是这个规则的一个特殊情况。
理论上,我没有理由想到为什么c++标准不能做出一个特殊的例外,允许在void
和非void
返回函数之间重载,这些函数具有相同的参数列表,重载分辨率与您提出的相同。然而,这种例外不太可能被批准,除非它被认为是合理有用的。
(顺便说一句,如果您认为这将非常有用,并且准备捍卫这一立场,请考虑将其发布到std-proposals邮件列表中。)
在C++
中,函数的返回类型不是编译器为唯一标识每个函数而生成的混乱名称的一部分。
- 。参数 参数类型
- 参数序列
是用来为每个函数生成唯一名称的参数。正是基于这些独特的混乱的名称,编译器才能理解调用哪个函数,即使名称相同(重载)。
Edit:一旦名称混淆包含了标准的返回类型,同时不允许调用函数而不忽略其返回类型,这是可能的。
- C++中的动态对象与非动态对象
- 平凡类型与非平凡类型的复制消除差异
- 如何编写 operator= 用于使用虚拟方法与非平凡成员的匿名联合
- std::异步与非静态成员函数
- std::原子与非原子变量的性能如何?
- 实例成员与静态成员与非类方法的开销
- Arduino trim() 和 replace() 方法返回从 'void' 到非标量类型'String'请求的转换
- 将 select() 与非基于文件描述符的输入一起使用
- 与非主线程的 GUI 线程通信
- 从标准::未来<void>到非标量标准::未来<bool>引发的错误转换
- MFC C++与非 MFC 控制台应用链接的静态库
- 这是重载提供与非静态成员函数相同接口的静态成员函数的优雅方法吗?
- “如果 constexpr”与非安置新问题
- 将 std::error_code 与非整数值一起使用
- 模板成员函数签名冲突与非模板成员功能签名
- 为什么可变参数模板与非可变参数模板不同?
- 如何将 shmat 与非 NULL 页面对齐的 shmaddr 一起使用?
- C++ lambda 到 std::函数错误与非常量字符串
- 函数的内联版本返回的值与非内联版本不同
- c++重载返回void与非void