【问题标题】:Call to a constructor cannot appear in a constant-expression对构造函数的调用不能出现在常量表达式中
【发布时间】:2012-07-03 22:42:49
【问题描述】:

对于我的新手问题,我很抱歉,但我对 C++ 了解不多。任何人都可以回答为什么我在编译以下代码时收到错误“错误:对构造函数的调用不能出现在常量表达式中”;

class EliminationWeight
{
 public:
    typedef double Type;
    static const Type MAX_VALUE = __DBL_MAX__;
    static const Type MIN_VALUE = -__DBL_MAX__;
};

我使用 Ubuntu 12.04 和它附带的 gcc。这不是我的代码,我知道这段代码可能 100% 可以正常工作(可能在旧版本的 gcc 或其他编译器中)。有没有快速修复它的方法?

提前感谢您的任何回答,这实际上是我第一次在 SO 提出问题。

【问题讨论】:

标签: c++


【解决方案1】:

Call to a constructor cannot appear in a constant-expression 是一条 GCC 错误消息,在这里对我来说没有任何意义。例如,Clang 接受您的代码时会发出一些警告:

test.cpp:31:23: warning: in-class initializer for static data member of type
      'const Type' (aka 'const double') is a GNU extension [-Wgnu]
    static const Type MAX_VALUE = __DBL_MAX__;
                      ^           ~~~~~~~~~~~

无论如何,在类主体中初始化 double 是非标准的。您应该单独进行初始化:

class EliminationWeight
{
 public:
    typedef double Type;
    static const Type MAX_VALUE;
    static const Type MIN_VALUE;
};

然后在一个源文件中(不是头文件):

const EliminationWeight::Type EliminationWeight::MAX_VALUE = __DBL_MAX__;
const EliminationWeight::Type EliminationWeight::MIN_VALUE = -__DBL_MAX__;

通常,您只能在类主体中初始化具有整数类型的静态成员变量,尽管这已在 C++ 0x11 中进行了扩展。另见Initializing const member within class declaration in C++

【讨论】:

  • ...并且该警告告诉您代码是非标准的,并且仅由于扩展而起作用。问题是只有整数类型才能以这种方式初始化。它不是任何方式、形状或形式的“错误”。
  • 确实如此,我只是说错误信息是错误的。将更新答案。
  • -1 已删除,尽管我会以更一般的方式描述问题,例如; “只有整数类型(包括枚举值)才能以这种方式初始化。”
  • 现在我得到错误:'const Type EliminationWeight::MIN_VALUE' 之前在这里定义
  • @AlexandrosE.:确保您没有定义 MIN_VALUE 两次。此外,初始化部分通常应该转到源文件。
【解决方案2】:

我只是偶然发现了这个完全相同的问题。我们正在讨论的代码是Contraction Hierarchies implementation by KIT 的一部分。

这是尝试使用 gcc 4.8 编译代码时出现的唯一编译错误。

@vitaut 建议的修复是完成这项工作所需要的。但是请注意,main.cpp 中已经存在以下几行:

// doesn't look nice, but required by the compiler (gcc 4)
...
const EliminationWeight::Type EliminationWeight::MAX_VALUE;
const EliminationWeight::Type EliminationWeight::MIN_VALUE;

如果您决定创建一个 EliminationWeight.cpp 文件以与您的 EliminationWeight.h 一起使用并将其包含在 Makefile 中,那么这些行就是您看到与上述不同的错误的原因:

main.cpp:86:31: error: uninitialized const ‘EliminationWeight::MAX_VALUE’ [-fpermissive]
 const EliminationWeight::Type EliminationWeight::MAX_VALUE;
                               ^
main.cpp:87:31: error: uninitialized const ‘EliminationWeight::MIN_VALUE’ [-fpermissive]
 const EliminationWeight::Type EliminationWeight::MIN_VALUE;
                               ^

解决方案是要么删除 main.cpp 中的这些行,要么将它们用于实际初始化。我选择了后者,现在的线条看起来像这样:

const EliminationWeight::Type EliminationWeight::MAX_VALUE = std::numeric_limits< EliminationWeight::Type >::max();
const EliminationWeight::Type EliminationWeight::MIN_VALUE = -std::numeric_limits< EliminationWeight::Type >::max();

请注意,我已将std::numeric_limits 模板用于EliminationWeight::Type typedef 定义的类型。这意味着我们只需要更改 typedef 以使用不同的类型。

但是,在 main.cpp 中使用这些要求我们包含 numeric_limits 模板的标头。它在不包含标题的情况下也对我有用,但这可能是因为它是通过其他一些包含的文件包含的。为了干净的代码,无论如何我们都应该包含它。

#include <limits>

另请注意,C++11 为 numeric_limits 模板提供了一个新函数 lowest,这意味着您可以将最后一行替换为以下内容:

const EliminationWeight::Type EliminationWeight::MIN_VALUE = std::numeric_limits< EliminationWeight::Type >::lowest();

但是,C++ reference on lowest 将浮点类型的返回值指定为

依赖于实现;通常,max() 的负数

所以我不确定你是否通过使用这个功能获得了很多。它确实为您提供了看起来更清晰的代码,但似乎返回值有些未指定。

【讨论】:

    【解决方案3】:

    当我要在类 Alg 中声明和实例化类 Time 的静态 const 对象时遇到了这个问题。当我在类中声明成员变量并在外部实例化它时,它起作用了,如下所示:

    Class Alg {
    
        public: 
        .
        .
    
        static const Time genTime;
        .
        .
    }
    
    const Alg::genTime = Time(0,0,1,0);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-29
      相关资源
      最近更新 更多