【问题标题】:How to get a public constant from an object? [duplicate]如何从对象中获取公共常量? [复制]
【发布时间】:2019-08-14 18:42:08
【问题描述】:

当我这样做时

Txtbin a;

switch(err){
    case a.ERR_EMPTY_IMAGE:
        std::cerr << "Error: Image is empty\n" << std::endl;
        break;
}

我收到此错误

txtbin.cpp: 在函数'int main(int, char**)': txtbin.cpp:97:11: 错误:‘a’的值在常量表达式中不可用 案例 a.ERR_EMPTY_IMAGE: ^

常量ERR_EMPTY_IMAGE在类中定义如下:

public:
    const int ERR_EMPTY_IMAGE   = 2;

【问题讨论】:

  • 让它static
  • @user207421 怎么样?
  • 这可能会让人感到震惊,但请在声明中添加关键字static。需要进行进一步的更改,但我希望任何有能力的程序员都能够进行更改,就像这个一样。

标签: c++ class switch-statement constants


【解决方案1】:

总之

在您的课程Txtbin 中,将 const 定义为静态:

public:
    static const int ERR_EMPTY_IMAGE   = 2; 

然后

switch(err){
    case Txtbin::ERR_EMPTY_IMAGE:
        std::cerr << "Error: Image is empty\n" << std::endl;
        break;
}

很长,所有的解释

为什么是静态的?

事实上,您初始化常量的方式清楚地表明它并不特定于任何对象:您不打算在类的两个对象中为 ERR_EMPTY_IMAGE 设置不同的值。

告诉编译器的正确方法是使这个常量static。这使得常量独立于类的任何对象。然后,您可以在任何需要的地方仅使用Txtbin::ERR_EMPTY_IMAGE 引用它。

一旦它是静态的,您还可以在switch 中继续使用a.ERR_EMPTY_IMAGE,因为编译器会发现它不需要非常量对象a 来确定值。

还要注意,对象的大小也会更小,因为不需要在每个实例中都复制静态值。

为什么这里 const 不够用?

您可以很好地拥有一个公共const,该const 对于类的每个对象都不同:

class Test2 {
public:
    const  int ERR_EMPTY_IMAGE;    
    Test2(int x) : ERR_EMPTY_IMAGE{x} {}
};
 
Test2 c(5), d(6); 
cout << "Test2 c ->"<< c.ERR_EMPTY_IMAGE<<" d->"<< d.ERR_EMPTY_IMAGE<<endl; 

const 仅表明一旦构造对象,成员的值就不会改变。这就是为什么您的编译器首先抱怨的原因: const 不足以让编译器在编译时定义它。证明:

class Test1 {
public:
    const  int ERR_EMPTY_IMAGE   = 2;  
    Test1() = default;                  // default constructor 
    Test1(int x) : ERR_EMPTY_IMAGE{x} {}
};

Test1 b;  
Test1 b_ouch(9); 
cout << "Sizeof b: "<< sizeof(b) <<endl;  
cout << "Test1 b ->"<< b.ERR_EMPTY_IMAGE<<" b_ouch->"<< b_ouch.ERR_EMPTY_IMAGE<<endl; 

这里是上面所说的online demo

constexpr 会更好吗?

constexpr 是告诉编译器您希望表达式在编译时保持不变的方式。所以你可以在case 中使用这种表达方式。

现在由于上述所有原因,constexpr 无论如何都要求您的成员变量为static

public:
    constexpr static int ERR_EMPTY_IMAGE   = 2;   

在您的情况下,constexpr 的主要优点是更快地突出任何误解。因为你很可能像这样定义你的成员

public:
    const static int ERR_EMPTY_IMAGE; 

并在类外初始化它的值。这使得它非常棘手。从语义上讲,对于 C++,这仍然是一个静态常量(即它的值永远不会改变)。并且在初始化常量的编译单元中,由于常量传播,它将被用作编译时常量。但在其他编译单元中,它的值在编译时是未知的(它可能只有在链接时才知道)。

使用constexpr 而不是const,编译器会立即抱怨声明中缺少初始化。所以使用它可能是一个优势,至少如果你不必使用一些旧的编译器。

【讨论】:

  • constexpr 会更好吗?假设你的编译器支持 C++11
  • @Ayxan constexpr static 然后 - 见 here
  • @Ayxan 为什么会更好?
  • @Ayxan:从 C++17 开始,是的,在此之前 constexpr 常量有一些非常奇怪的东西
  • @user207421 因为 constexpr 在编译时被显式解析
猜你喜欢
  • 2019-08-18
  • 2015-09-03
  • 2016-07-19
  • 1970-01-01
  • 1970-01-01
  • 2019-08-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多