如何从对象获取公共常量?

时间:2019-03-24 09:21:55

标签: c++ class switch-statement const

当我这样做

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;

1 个答案:

答案 0 :(得分:0)

简而言之

在您的类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来引用它。

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

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

为什么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; 对于该类的每个对象都是不同的:

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; 

const只会告诉成员一旦构造对象,成员的值就不会改变。这就是为什么您的编译器在第一个实例中抱怨的原因:const不足以使编译器在编译时定义它。证明:

constexpr

online demo是上述内容

constexpr会更好吗?

case是对编译器说的一种方法,您希望表达式在编译时是恒定的。因此,您可以在constexpr中使用这种表达方式。

现在,由于上述所有原因,static仍然要求您的成员变量为public: constexpr static int ERR_EMPTY_IMAGE = 2;

constexpr

在您的情况下,public: const static int ERR_EMPTY_IMAGE; 的主要优点是可以更快地突出任何误解。因为您很可能会这样定义您的成员

constexpr

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

使用const而不是{{1}}时,编译器会立即告诉您声明中缺少初始化内容,从而立即抱怨。因此,至少在不必使用某些较旧的编译器的情况下,使用它可能是一个优势。