【问题标题】:Why does the compiler claim this class method has no return value?为什么编译器声称这个类方法没有返回值?
【发布时间】:2014-02-08 04:17:17
【问题描述】:

我从 Eclipse 得到的错误是“No return, in function return non-void”。我添加了 default: case 以查看它是否会消除错误,但没有 bean。我认为返回一个右值是可以的,因为它会按值复制到堆栈中,因此当 getLogLevelName() 的局部变量超出范围时,将存在字符串的副本。确实,调用代码有效,但错误对我来说很神秘。

std::string bmd2::Logger::getLogLevelName(bmd2::Logger::LogLevel logLevel) throw ()
{
  switch (logLevel)
  {
    case bmd2::Logger::LogLevel::LOG_ERROR:
      return std::string ("ERROR");
      break;
    case bmd2::Logger::LogLevel::LOG_WARNING:
      return std::string ("WARNING");
      break;
    case bmd2::Logger::LogLevel::LOG_INFO:
      return std::string ("INFO");
      break;
    case bmd2::Logger::LogLevel::LOG_DEBUG:
    default:
      return std::string ("DEBUG");
      break;
  }
}

【问题讨论】:

  • std::string 有一个隐式转换构造函数,所以你可以只做return "string text"; 因为std::string 是返回类型,所以会自动创建一个。
  • 明确一点也没有错
  • 去掉所有无法访问的break语句。
  • 我以为是eclipse CDT的错误提示,gcc或者msvc都可以编译。
  • Eclipse 不够聪明,无法处理不必要的中断语句。在我删除休息后,日食很高兴。

标签: c++ c++11 enums switch-statement


【解决方案1】:

Eclipse 将此报告为错误,因为无论它使用什么 C++ 分析工具/库,它都没有推断出 switch 语句中的 default 情况实际上是函数的结尾。即使 Eclipse 另有说明,这也应该表现得非常好。也许安抚 Eclipse 的更好方法是将默认的 return 语句放在 switch 语句之后。

std::string bmd2::Logger::getLogLevelName(bmd2::Logger::LogLevel logLevel) throw ()
{
  switch (logLevel)
  {
    case bmd2::Logger::LogLevel::LOG_ERROR:
      return std::string ("ERROR");
    case bmd2::Logger::LogLevel::LOG_WARNING:
      return std::string ("WARNING");
    case bmd2::Logger::LogLevel::LOG_INFO:
      return std::string ("INFO");
    case bmd2::Logger::LogLevel::LOG_DEBUG:
    default:
      // We will return the default value after the switch statement.
      break;
  }
  // Return default value.
  return std::string ("DEBUG");
}

【讨论】:

  • 会删除所有的break-after-the-return pacify eclipse吗?不喜欢这个结构似乎很愚蠢,因为有一个“默认”路径,所以我希望有别的东西把它扔掉......就像不必要的休息。
  • 如果 Eclipse 没有检测到 cases 和 default 中不可避免的 return,我怀疑在开关中删除 return 之后的 break 是否会安抚 Eclipse。但是,returns 之后的 breaks 是多余的,删除它们也无妨。
  • @user2864740 根据@jakeliquorblues 的说法,当他删除多余的breaks 时,Eclipse 很高兴。
【解决方案2】:

您收到此错误是因为您的编译器 (Eclipse) 在 switch 范围内看不到 return-statement。你可以添加

return std::string("CAN-BE-ANY-THING");  // this line will never be called though

在函数结束时摆脱错误。

【讨论】:

    【解决方案3】:

    在 C++ 中,编写一个声明为返回值但实际上从未返回值的函数是完全合法的。只有在运行时执行实际上从这样的函数返回而不返回值时才会出现问题。

    // this program is perfectly legal and well behaved; just don't ever call foo()
    int foo() {}
    
    int main() { return 0; }
    

    但程序员希望编译器帮助他们生成正确且行为良好的程序,因此编译器试图找出程序何时可能做坏事并告诉程序员这些事情。问题是 C++ 定义了“坏事”,因此在编译时完美地确定它们是否真的会发生需要解决停机问题。

    很明显,编译器不会这样做,所以在试图帮助程序员时,有时编译器会出错。希望编译器在大多数情况下都能很好地处理大多数真实代码的情况,但不可避免地会有编译器无法处理的情况,因此会导致误报(编译器会警告无法真正发生的问题)或假阴性(编译器未能警告可能发生的问题)。

    您有两个基本选择:告诉编译器停止尝试以产生此消息的特定方式来帮助您(通过禁用此警告),或者您可以更改代码以便编译器的不完全正确的分析仍然能够弄清楚它总是返回一个值。


    C++ 以外的语言采用了其他方法,例如简单地将无法返回值设为非法,这样简单的分析就可以看到返回值。例如,C# 明确地采用该路由,以便编译器可以检查它并完全正确。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-17
      • 1970-01-01
      • 2021-01-11
      • 1970-01-01
      相关资源
      最近更新 更多