C ++重载返回void与非void

时间:2014-03-17 04:19:01

标签: c++ overloading

基于是否存在返回值,C ++是否有任何特殊原因禁止重载?像这样:

void f();  //(1)
int f();  //(2)

int main(){
    f(); // calls (1)
    int x = f(); // calls (2)
    return x;
}

每当忽略返回值时都会调用void-variant,因此重载决策不应该有任何问题。对于vector::pop_back()之类的东西,即使在标准库中也很有用。那为什么不允许这样做?

编辑:已经注意到,也可以在void上下文中调用非void函数。我知道这件事。我只是希望编译器更喜欢void函数(如果有的话)。

5 个答案:

答案 0 :(得分:2)

可以在忽略返回值的上下文中调用返回非void类型的函数。例如,C函数printf()的返回值类型为int,但在实践中很少使用。

换句话说,您可以使用:

调用函数int f()
f();

忽略返回值,仅使用副作用。

答案 1 :(得分:2)

这是一种语言规则,在C ++ Programmin语言第4版中,您可以阅读:

  

重载分辨率不考虑返回类型。原因是   保持个体经营者的决议(§18.2.1,§18.2.5)或   函数调用独立于上下文。

但是看看你的例子,它可以清楚地说明应该调用哪个函数:

f(); // calls (1)
int x = f(); // calls (2)

在(1)中为void版本,而在(2)中为非void版本。您可以在此答案Function overloading by return type?中读到有些语言允许在返回类型上进行重载。

在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;
}

答案 2 :(得分:0)

是的。在C ++或Java中,方法签名可识别任何给定类中的方法,此处的签名定义为方法的名称以及方法接受的参数的类型和数量。返回类型不是方法签名的一部分,因此在这些编程语言中不允许使用仅因其返回类型而不同的方法重载。在您的示例中: int x = f(); 您假设用户将键入 int x ,但程序员并不是真的必须这样做!在前言中,我解释了当用户调用 f() 时方法签名时,编译器无法识别您是在调用第一个还是第二个。也就是说,一些现代编程语言允许基于返回类型进行重载。您可以找到更全面的解释here

答案 3 :(得分:0)

C++中,函数的返回类型不是由编译器生成的用于唯一标识每个函数的错位名称的一部分。

  • 否。参数
  • 参数类型
  • 参数序列

是用于为每个函数生成唯一的受损名称的参数。正是基于这些独特的错位名称,即使名称相同(重载),编译器也可以理解调用哪个函数。


编辑:一旦名称修改包含了标准的返回类型,同时不允许在不忽略其返回类型的情况下调用函数,就有可能。

答案 4 :(得分:0)

  

只能在返回类型上有所不同的函数声明不能​​重载。

void f()int f()的示例只是此规则的一个特例。

理论上我没有理由想到为什么C ++标准不会产生特殊异常并允许void和非void返回函数之间的重载与具有重载的相同参数列表分辨率与您提出的分辨率相同。但是,除非被认为合理有用,否则不太可能批准此类例外......

(顺便说一句,如果您认为这非常有用,并且准备为这个职位辩护,请考虑发布到std-proposals邮件列表。)