7

MyClass.h

class MyClass
{
public:

static const int cTotalCars;

private:

int m_Cars[cTotalCars];
};

MyClass.cpp

#include "MyClass.h"
const int MyClass::cTotalCars = 5;

The above code doesn't work because it will say "expected constant expression" for the m_Cars array.

class MyClass
{
public:

static const int cTotalCars = 5;

private:

int m_Cars[cTotalCars];
};

The above will work, but I am told that I should always define static members in the CPP file, outside the class definition. What can I do?

5 Answers 5

7

Static const members of simple type are a exception to that rule, so you latter code is correct.

This exception is a fairly modern one (from C++98, but not implemented by every compiler until a few years later) so many old-fashioned teachers are not yet aware of it. They prefer the idiom:

class MyClass
{
public:
   enum { cTotalCars = 5 };

private:
    int m_Cars[cTotalCars];
};

That behaves exactly the same, but makes little sense nowadays.

Sign up to request clarification or add additional context in comments.

4 Comments

"static const members of simple type are an exception to that rule" is not correct. You probably mean integral rather than simple but even with integral constants, you must define the static member if it is used according to the language, which roughly means used as an lvalue (roughly it's address is taken). for a simple example where that definition is required, consider: void f( const int & ); f( MyClass::cTotalCars );
The problem that I had with my latter code is that when I would change the value and rebuild, it would not be updated when other classes accessed it. They would still have the old value. Doing a clean rebuild would fix the problem, but I'm not sure why. If I use my former code, I have the array issue but the value is updated when accessed from an outside class without a clean build.
@DavidRodríguez-dribeas You are right about the integral. GCC allows also using float like that, but I didn't noticed that it is an extension. And about using the variable as an lvalue, you are also right, of course.
@user987280 But that is a problem with your compilation system, that doesn't check the dependency to the header file properly. The same would happen if you change, say, an inline function or an enumeration value.
3

The above will work, but I am told that I should always define static members in the CPP file, outside the class definition. What can I do?

Well, what you have been suggested to do: define the static members in the CPP. Note that in the code above the static member is not defined even if the value is stated. The proper final code would look like:

// .h (ignoring all but the static member)
class MyClass {
   static const int cTotalCars = 5;        // declaration and initialization
};
// .cpp
static const int MyClass::cTotalCars;      // definition (cannot have value!)

The definition in the .cpp file is what actually reserves the space for the variable when used as an lvalue. For a simple test that verifies that without that line the variable is not defined you can do:

void f( const int & x ) {}
int main() {
   f( MyClass::cTotalCars );
}

Without the line in the .cpp file the code above will trigger a linker error pointing to the missing definition of MyClass::cTotalCars. The problem with the code is that it uses the static const member (by the definition of use in the standard), and that requires the member to be defined. While the case of using the constant to define the array size does not constitute use.

5 Comments

Thanks for the information. I won't ever need to get the address of this variable or use it as a reference, but that is good to know. I am more interested in the problem I just described in repsonse to rodrigo's post about the value not getting updated after a rebuild when using my latter code.
@user987280: Your problem is not with the language, but rather with your build system. The dependencies are not correctly set in your code base and as a result not everything that should be rebuilt is actually rebuilt. Take the time to fix the build system and ensure that all dependencies are right.
I'm not sure I understand. What type of dependencies would I be looking for? Could you give an example of what you are describing?
@user987280: If changing the constant in the header did not trigger the rebuilding of all code that uses that constant then the problem is that the build system is not tracking that the uses depend on the header (or else those would have been recompiled automatically), and that is the problem you should fix.
Oh okay, I see what you mean. I don't know how to go about fixing that other than looking in the VS build settings, but I don't see anything there. I just reproduced the behavior in another class in another cpp file, so at least it's consistent.
0

I would rather use a #define C_TOTAL_CARS 5, then static const int cTotalCars = C_TOTAL_CARS; and then also, int m_Cars[C_TOTAL_CARS];.

4 Comments

Why? Why relinquish the benefit of scope for no gain?
@Geoffroy if it works, then it answers the "what can I do?" question, and thus answers the question. Now, my C++ might be extremely old fashioned though (as GMan kind of implies :D)
Your solution works, but the question was about static members. And the OP already gave a working solution :)
@Geoffroy this is not exactly how I understood the question. Now, the more I read it, the more I agree with you... :)
0

If is was a static int you would need to place it into the .cpp file. You do not need the keyword static in this instance as all you want is a constant. Just use const int cTotalCars = 5;. It is better than #define as you have type info and also it has a symbol that can be viewed in a debugger.

Comments

0

It just can't works if you define size of the array is set in cpp file. All class clients should know the size of class instance but they just have no idea about .cpp file because you only put #include "MyClass.h" in client-files.

In other words - your class definition is varies depending on the cpp-file which is not used while compile files that uses MyClass.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.