tags:

views:

406

answers:

5

I'm trying to decide what the best option would be for when an object has some traits that won't change, and are needed throughout its functions.

  1. Static const members
  2. Const members

It seems to me like the real reason for a static member is to have a variable that can be changed, and thus affect all other objects of the same class. However, I've had people recommend class "invariants" to be static const members. I'm looking for some insight regarding the recommended approach to establishing class constants, and reasons why.

+11  A: 

"Won't change" is not precise enough. The main question here is whether different objects of the class need to have different values of these const members (even if they don't change during the object's lifetime) or all objects should use (share) the same value.

If the value is the same for all objects of the class, then, of course, it should be a static const member of the class.

If different objects might require different values, then it should be just a non-static const member.

AndreyT
By "won't change" I meant the value is the same for all objects of the class.
trikker
In that case you have no reason not to make it `static const`. A non-static const will work as well (aside from some specific/exotic cases), but it will result in complately unnecessary waste of memory.
AndreyT
Yes, that's the gist I got.
trikker
+9  A: 

A const member should be used when that member doesn't change on a per-instance basis. A static const member should be used when that member doesn't change on a per-class basis. In other words, no matter how many instances you create, the static const member remains fixed between all instances whereas the const member is constant only for a specific instance.

I'm not sure if that's what you're looking for since that's merely an explanation of how they behave, but I hope it helps somewhat.

Dustin
Precisely Explained.
novice_coder
A: 

One reason would be that regular const members will take up more memory... i.e. for each object of the class you create, one const member object will be included in that object and initialized.

If it's a static const member, on the other hand, then only one object will be created and initialized, no matter how many objects of the class you create, and all class objects will share the same object.

To demonstrate, try compiling it both ways, creating several objects, and doing a printf("%p", &theConstMemberObject)... when it's static, you'll see they all print the same pointer value; when it's not static, they each have their own object and thus they each print a different pointer value.

Jeremy Friesner
A: 

You would make a member variable static const because, with it being unchanging, you can reuse the same copy of it, shared by all instances of your class. As opposed to each instance having its own (identical) copy of the constant value.

You would expect the compiler to be smart enough to do this optimisation for you though, and I suspect it does. It is a nice habit to get into though.

DanDan
A const member variable may be initialised in the constructor so may vary for different instances of the class.
danio
You must be careful with what you can assume the compiler to do for you. As @danio points out, if the header is reused in different compilation units, there is only one compilation unit where the compiler could know that the value is shared, as opposed to many that must define a compatible memory layout. The one that knows, cannot change the memory layout as it would break code in all the other compilation units.
David Rodríguez - dribeas
A: 

my preference is not to use static const members as it always seem to create more coupling than const members; sometimes confusion w.r.t diamond inheritance hierarchy where the final class inherits from 2 super classes (1 class is inherited public; the other is inherited virtual public) then defining a static const member that points to a dynamic memory region via new, malloc, calloc etc would result in a double free error.

e.g. here's the output of a simple diamond inheritance situation ray:~ ray$ ./multiinheritance Base() called Derived1() called Base() called Derived2() called Final() called ~Final() called ~Derived2() called ~Base() called freeing memory ~Derived1() called ~Base() called freeing memory multiinheritance(475) malloc: *** error for object 0x100150: double free *** set a breakpoint in malloc_error_break to debug ray:~ ray$

Here's the code: ` #include <iostream> #include <string>

class Base { public: Base() { std::cout << "Base() called " << std::endl; } virtual ~Base() { std::cout << "~Base() called" << std::endl; std::cout << "freeing memory" << std::endl; delete i; } static const int* i; };

const int* Base::i = new int[5];

class Derived1 : virtual public Base { public: Derived1() { std::cout << "Derived1() called " << std::endl; } virtual ~Derived1() { std::cout << "~Derived1() called" << std::endl; } }; class Derived2 : public Base { public: Derived2() { std::cout << "Derived2() called " << std::endl; } virtual ~Derived2() { std::cout << "~Derived2() called" << std::endl; } };

class Final: public Derived1, public Derived2 { public: Final() { std::cout << "Final() called" << std::endl; } ~Final() { std::cout << "~Final() called" << std::endl; } };

int main(int argc, char** argv) { Final f; return 0; }

`

Raymond Tay
You should post the code from which you got that output, else it is useless. And I am not so sure it would be useful anyway, as I fail to see where the `const` vs `static const` would make a difference. From the description you give it sounds more like a problem with `static` vs `non-static` dynamic memory allocation and deletion.
David Rodríguez - dribeas
@dribeas, i was attempting to illustrate that sometimes mixing the `const` and `static const` with multiple/virtual inheritance
Raymond Tay