3

I have the following code in A.h:

class A
{
public:
    ...
private:
    ...
    const int X = 1;
    float Y[X];
    ...
};

This compiles fine if only header A.h is included in the project. But if I include A.h in let's say A.cpp it gives me strange errors as follows:

... warning: non-static data member initializers only available with -std=c++11 or -std=gnu++11 [enabled by default]

... error: invalid use of non-static data member 'A::X'

... error: from this location

Even when I change const int X = 1; (though I need it as a constant parameter), nothing changes.

p.s. If it makes sense I am using Qt 5.1

p.s.s. Actually making it static fixes the error. But why I have to do that?

Mike
  • 563
  • 5
  • 15
  • 32
  • I am sorry but I don't think this questions are duplicate. Please read my question ones more. – Mike Aug 22 '13 at 16:40
  • not trying to pick on your question, but this is exactly what you are asking. To answer the question simply, you can either make `X` static, or you can't do what you are looking to do. – Chad Aug 22 '13 at 16:47
  • I realize that. My question is "why?". I want to understand why I need to do so, not just copy paste. – Mike Aug 22 '13 at 16:49
  • If you want a constant data member and the value of the member will always be the same for every instance of the class, it makes no sense to have multiple copies of that member. It is better to have a single static member for all instances. – RobbieE Aug 22 '13 at 16:55
  • How did you compile it when you managed to make it work? Are you sure the header file got parsed? – olevegard Aug 22 '13 at 16:59
  • @olevegard That also surprised me :) – Mike Aug 22 '13 at 17:03
  • @RobbieE Thank you for explanation. So actually it does not influence the performance in any sense, right? – Mike Aug 22 '13 at 17:04
  • That depends on your particular case. Because static data members live at the class level, not the instance level, they aren't copied along with the instance data when copies are needed. – RobbieE Aug 22 '13 at 17:10
  • Thanks, now it is more clear – Mike Aug 22 '13 at 17:11
  • By the way, this has nothing to do with Qt. It's a c++ thing. – RobbieE Aug 22 '13 at 17:13

5 Answers5

5

The first problem is that you're compiling against an old version of C++, which didn't allow non-static (that is, per-object rather than per-class) members to be initialised in their declaration. You can either compile against C++11 (as the error message suggests); or initialise it in the constructor; or make it static, if you don't need a separate value for each object you create.

The second problem is that an array size must be a compile-time constant. A non-static member, const or otherwise, doesn't fit the bill. In principle, it could have different values in different objects (even if it's initialised in the declaration like that, it could be overridden by one or more constructors), so there is no compile-time value. A static member does have a fixed value, so that can be used as an array size, if the value is available.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
3

Your intention is to have a constant variable inside the class.

Now this class is used to create many objects. Practically the class should allow each object to have different const value for the const data member , thus you can't initialize const members inside class.

const inside class members means the value is constant throughout the life time of the object.

That is why there exist a special initialization point called constructor initialization list rather than allowing the initialization in the constructor.

Now, if you're allowed to initialize the const member inside the constructor then you could re-assign it multiple times within the constructor itself which voilates the meaning of const(which means, assigned once and remains same throughout).

Hence the initialization of the const members should happen before the constructor, which is done in the initialization list. This gives you const members with different values for different objects if you want.

Also, note that the form of initialization in the constructor i(ii) is used to initialize the data members before entering the constructor

class A
{
    const int i;
    public:
       A(int ii): i(ii)
       {
          // i  = 5; Can't do this since i is `const`
       }
};

Having said that, if you want all the object to share the same const value then you can use static const qualifier as pointed in others answers.

Also as Mike Seymour pointed out, for allocation of arrays or initializing const variables you need to have comiple-time constants, but consts inside class doesn't give you compile time constants, hence you will have to use the static const qualifier which makes it a compile time constant.

Uchia Itachi
  • 5,287
  • 2
  • 23
  • 26
2

You want to initialise X in the constructor initialisation list of A since it's a non-static const member of A:

class A {
    const int X;
public:
    A() : X(1) {
        // ...
    }
    // ...

that is to say that every object instantiated from class A has an int member named X (that's the non-static part i.e. it's not a member of the class) that is const (it can't be modified or reset so you have to initialise it in the constructor initialisation list, not the constructor body).

Paul Evans
  • 27,315
  • 3
  • 37
  • 54
0

That is simple

  • static const int X = 1;
  • enum { X = 1 }; // poor mans constexpr
  • Thank you for your answer. As you can see in the post - "Actually making it static fixes the error", I know that static fixes the error, but I don't really understand why I have to use static in this case. About "enum { X = 1 };" - why do I need this? – Mike Aug 22 '13 at 16:43
  • @Mike you can get an address of 'static const int' (hence some memory in the program), the enum value will have none (no memory, just a value). If you have C++ 11, use constexpr –  Aug 22 '13 at 17:35
0

Here's your culprit

    float Y[X];

Since you are trying to declare a float array by the name of Y having size X. But it is a non static, private member of the class.

Therefore, X will be in the symbol table, but the associated value isn't accessible during the compilation of above line and hence the warning and error.

  • `X` will not be in symbol table to aid in constant-folding. For `const` members inside class storage is always allocated hence constant folding fails. – Uchia Itachi Aug 22 '13 at 17:20