Private members: Static const vs. just const
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.
- Static const members
- 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.
"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.
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.
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.
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.
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;
}
精彩评论