Sunday, September 7, 2014

C++ Const keyword

You have to read pointer declarations right-to-left.

            const int x = 10;
            
x's value cannot be changed
            int const x = 10;
            
Same as above
            static int x = 10;
            
Same as above
            const int const x = 10; 
            
This is nonsense. Pointers have two different kinds of const qualifiers makes sense, one is for the pointer itself, the other for what the pointer points. But it doesn't make sense for int type to have two different kinds of const qualifiers. Just use one
            foo const* p;
            
p points to a constant foo. The foo object can't be changed. It means p points to an object of class foo, but p can't be used to change that foo object (naturally p could also be NULL). For example, if class foo has a const member function called inspect(), saying p->inspect() is OK. But if class foo has a non-const member function called mutate(), saying p->mutate() is an error
            const foo* p
            
Same as above
            foo* const p;
            
p is a const pointer to a foo. You can't change the pointer p, but you can change the foo object
            foo const* const p;
            
p is a const pointer to a const foo.You can't change the pointer p itself, neither can you change the foo object
            const foo* const p;
            
            foo const& r;
            
It means r aliases a foo object, but r can't be used to change that foo object. For example, if class foo has a const member function called inspect(), saying r.inspect() is OK. But if class foo has a non-const member function called mutate(), saying r.mutate() is an error
            const foo& r;
            
Same as above
            foo& const r;
            
This is nonsense. r is a const reference to a foo. But that is redundant, since references are always const. You can't reseat a reference. Never. With or without the const. In other words, "foo& const r" is functionally equivalent to "foo& x". Since you're gaining nothing by adding the const after the &, you shouldn't add it since it will confuse people — the const will make some people think that the foo is const, as if you had said "foo const& x".
            int GetValue() const;
            
This member function cannot change this pointer, i.e. the class members of this pointer. It can however change any other
            const foo GetValue();
            
            const int& GetValue();
            
Returns a const reference to the member variable if it's a getter method. This won't make copies and return.
            int* GetValue();
            
            const int* GetValue();
            
            const int GetValue() const;
            
            const int& GetValue() const;
            
            int* GetValue() const;
            
            const int* GetValue() const;
            

Note: const class objects can only call const member functions

Three ways you can initialize a const member variable.
1. Inside the class declaration
static const int x = 10;
2. Outside the class
class A
{
   static const int a;
};

const int A::a = 10;    //defining the static member outside the class
Note: static means there is a single copy of the variable for all instances of the object, constant or not. It creates just one copy of it for all the objects. It is a design choice that needs to be considered carefully.
3. In constructor initialization list
class A
{
  const int b;
  A(int c):b(c){}    //const member initialized in initialization list
};

Note: "mutable" keyword is used with member variables which we want to be able to change even on const class objects. Hence, mutable data members of const objects can be modified
class A
{
    int x;
    mutable int y;
    public:
    A()
    {
        x = 0;
        y = 0;
    }
    void func() const
    { 
        i++;  // Error, cannot modify 
        j++;  // Works, because y is mutable
    }
    void func()
    { 
        i++;  // Error, cannot modify 
        j++;  // Works, because y is mutable
    }
};

int main()
{
    const A constObj;
    constObj.func();    // Calls the const func method, since constObj is const object

    A obj;
    obj.func();         // Call the non const func method, since obj is non const object
}

No comments:

Post a Comment