开发者

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.

  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.


"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;
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜