In short
In your class Txtbin
, define the const as static:
public:
static const int ERR_EMPTY_IMAGE = 2;
then
switch(err){
case Txtbin::ERR_EMPTY_IMAGE:
std::cerr << "Error: Image is empty\n" << std::endl;
break;
}
In very long, with all the explanations
Why static ?
In fact the way you initialize your constant makes clear that it is not specific to any object: You do not intend to have a different value for ERR_EMPTY_IMAGE
in two objects of your class.
The right way to tell this to the compiler is to make this const static
. This makes the constant independent of any object of the class. You can then refer to it only with Txtbin::ERR_EMPTY_IMAGE
wherever you want.
Once it is static, you could also keep using a.ERR_EMPTY_IMAGE
in the switch
, since the compiler will find out that it doesn't need the non-const object a
to determine the value.
Note also that the size of the objects would also be smaller since static values do not need to be duplicated in every instance.
Why is const not sufficient here ?
You can very well have a public const
that is different for every object of the class:
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;
The const does only tell that the value of the member does not change once the object is constructed. And this is why your compiler complained in the first instance: the const is not sufficient for the compiler to define it at compile time. Proof:
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;
Here an online demo of what is said above
Would constexpr be even better ?
constexpr
is the way to say to the compiler that you expect the expression to be constant at compile time. So the kind of expression you could use in a case
.
Now for all the reasons explained above, constexpr
requires anyway your member variable to be static
:
public:
constexpr static int ERR_EMPTY_IMAGE = 2;
The main advantage of constexpr
in your case would be to highlight any misunderstandings sooner. Because you could very well have your member defined like this
public:
const static int ERR_EMPTY_IMAGE;
and initialize its value outside the class. This makes it very tricky. Semantically, for C++ this is still a static constant (i.e. its value will never change). And in the compilation unit in which the constant is initialized, it'll be used as a compile time constant thanks to constant propagation. But in other compilation units, its value is not known at compile time (it might be known only at link time).
With constexpr
instead of const
the compiler would immediately complain by telling you that the initialization is missing in the declaration. So it could be an advantage to use it, at least if you do not have to use some older compiler.