当我这样做
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;
答案 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
,该公共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是上述内容
case
是对编译器说的一种方法,您希望表达式在编译时是恒定的。因此,您可以在constexpr
中使用这种表达方式。
现在,由于上述所有原因,static
仍然要求您的成员变量为public:
constexpr static int ERR_EMPTY_IMAGE = 2;
:
constexpr
在您的情况下,public:
const static int ERR_EMPTY_IMAGE;
的主要优点是可以更快地突出任何误解。因为您很可能会这样定义您的成员
constexpr
并在类外部初始化其值。这使其非常棘手。语义上,对于C ++,这仍然是一个静态常量(即,其值永远不会改变)。在常量被初始化的编译单元中,由于常量的传播,它将被用作编译时常量。但是在其他编译单元中,其值在编译时未知(可能仅在链接时已知)。
使用const
而不是{{1}}时,编译器会立即告诉您声明中缺少初始化内容,从而立即抱怨。因此,至少在不必使用某些较旧的编译器的情况下,使用它可能是一个优势。