【问题标题】:c++ - expression did not evaluate to a constant - using constant from another classc++ - 表达式没有计算为常量 - 使用来自另一个类的常量
【发布时间】:2019-07-26 18:51:25
【问题描述】:

[我的代码很大,所以我只粘贴了与我相关的部分,如果您需要查看更多内容,请告诉我,谢谢]

我在一个类(动画)中定义了一个常量,但现在我将该类一分为二(AnimationsDefinition 和 AnimationsInstance),我不能将该常量从一个类使用到另一个类

我在 AnimationsInstance.h 之前包含了 AnimationsDefinition.h

common.h

#include "animationsDefinition.h"
#include "animationsInstance.h"

编译器抱怨无法计算常量

下面的代码曾经可以工作,但现在我在另一个类中使用它,它不再工作了

我得到的错误:

error C2131: expression did not evaluate to a constant
note: failure was caused by non-constant arguments or reference to a non-constant symbol
note: see usage of 'EAST'

AnimationsDefinition.cpp

#include "common.h"

const int AnimationsDefinition::WEST    = 0;
const int AnimationsDefinition::SOUTH   = 1;
const int AnimationsDefinition::NORTH   = 2;
const int AnimationsDefinition::EAST    = 3;

...

AnimationsDefinition.h

#pragma once

class AnimationsDefinition
{
public:
    static const int WEST;
    static const int SOUTH;
    static const int NORTH;
    static const int EAST;
    ...

AnimationsInstance.cpp

#include "common.h"

void AnimationsInstance::update(float tpf)
{
    switch (direction)
    {
        case AnimationsDefinition::EAST: <<<<<<<<< compilation error
        {
            ...

任何帮助表示赞赏

问候

【问题讨论】:

  • 在这里可以工作:godbolt.org/z/LolvUT
  • 不错的应用,我去看看...
  • 我将在另一个类中重新定义相同的常量,这不是很好,但我没有时间去了解 Visual Studio C++ 编译器的奇怪之处
  • 您所做的似乎是枚举的常见用例。您是否有特定的原因决定不使用枚举来实现它?像这样:godbolt.org/z/9_1Z2R
  • “我的代码 [相当] 大...”正是您应该创建一个 minimal reproducible example 来演示问题的原因。

标签: c++ class constants


【解决方案1】:

只有在遇到初始化器之后,常量变量才能用作常量表达式。在这种情况下,可以通过将初始化程序移动到标题中来实现。

请注意,将初始化程序移动到标头中类定义内的声明中不会使该声明成为变量的定义。定义必须仍然保留在源文件中,只是没有初始化程序。

好的,我发现我可以在类本身中定义它们,因为它们是静态的

只有在声明 inline 时,才能在类本身(或一般的标头)中定义它们。


但是,对 switch 案例使用(范围)枚举更为传统。

【讨论】:

  • 是的,谢谢 ;-) 我不明白为什么不允许在另一台机器/其他项目上执行此操作..可能是编译器问题
【解决方案2】:

您可以在类本身中初始化static const 变量。

class AnimationsDefinition
{
public:
    static const int WEST = 0;
    static const int SOUTH = 1;
    static const int NORTH = 2;
    static const int EAST = 3;
};

但是,如果您想避免违反 ODR,则需要正确定义它们。

所以使用constexpr 说明符,这意味着inline 用于static 数据成员。并且inline static 数据成员可以在类定义本身中定义。

class AnimationsDefinition
{
public:
    static constexpr int WEST = 0;
    static constexpr int SOUTH = 1;
    static constexpr int NORTH = 2;
    static constexpr int EAST = 3;
};

根据[class.static.data]/3

内联静态数据成员可以在类定义中定义,并且可以指定一个大括号或等号初始化器。

【讨论】:

  • No。这些将需要定义,除非您非常小心地避免使用 ODR(以及为什么要这样做?)改用 constexpr inline 事物(或范围枚举)
  • @LightnessRacesinOrbit:谢谢。更新了帖子。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多