tags:

views:

671

answers:

7

Given a declaration like this:

class A {
public
    void Foo() const;
};

What does it mean?

Google turns up this:

Member functions should be declared with the const keyword after them if they can operate on a const (this) object. If the function is not declared const, in can not be applied to a const object, and the compiler will give an error message.

But I find that somewhat confusing; can anyone out there put it in better terms?

Thanks.

+1  A: 

that will cause the method to not be able to alter any member variables of the object

John Boker
+3  A: 

Const functions are not allowed to modify any member variables. For example:

class A
{
    int x;
    mutable int y;

    void f() const
    {
      x = 1; // error
      y = 1; // ok because y is mutable
    }
};
1800 INFORMATION
+2  A: 

C++ objects can be declared to be const:

const A obj = new A();

When an object is const, the only member functions that can be called on that object are functions declared to be const. Making an object const can be interpreted as making the object readonly. A const object cannot be changed, i.e. no data members of the object can be changed. Declaring a member function const means that the function is not allowed to make any changes to the data members of the object.

dfjacobs
Err... const A * obj = new A() ; ... You forgot the "star"... :-)
paercebal
+8  A: 

Consider a variation of your class A..

class A {
public:
    void Foo() const;
    void Moo();

private:
    int m_nState; // Could add mutable keyword if desired
    int GetState() const   { return m_nState; }
    void SetState(int val) { m_nState = val; }
};

const A *A1 = new A();
A *A2 = new A();

A1->Foo(); // OK
A2->Foo(); // OK

A1->Moo(); // Error - Not allowed to call non-const function on const object instance
A2->Moo(); // OK

The const keyword on a function declaration indicates to the compiler that the function is contractually obligated not to modify the state of A. Thus you are unable to call non-const functions within Foo() nor change the value of member variables.

To illustrate, Foo() may not invoke SetState() as it is declared non-const, GetState() however is ok b/c it is explicitly declared const. The member m_nState may not be changed either unless declared with the keyword mutable.

One example of this usage of const is for 'getter' functions to obtain the value of member variables.

@1800 Information: I forgot about mutable!

The mutable keyword instructs the compiler to accept modifications to the member variable which would otherwise cause a compiler error. It is used when the function needs to modify state but the object is considered logically consistent (constant) regardless of the modification.

Henk
Great answer - really clear and succinct. Got my +1
John Sibly
+4  A: 

This is not an answer, just a side comment. It is highly recommended to declare variables and constants const as much as possible.

  1. This communicates your intent to users of your class (even/especially yourself).
  2. The compiler will keep you honest to those intentions. -- i.e., it's like compiler checked documentation.
  3. By definition, this prevents state changes you weren't expecting and can, possibly, allow you to make reasonable assumptions while in your methods.
  4. const has a funny way of propagating through your code. Thus, it's a really good idea to start using const as early and as often as possible. Deciding to start const-ifying your code late in the game can be painful (easy, but annoying).

If you're using a language with static, compile time checks it's a great idea to make as much use of them as possible... it's just another kind of testing really.

Pat Notz
+1  A: 

Two suggested best practices from experience:

(1) Declare const functions whenever possible. At first, I found this to be just extra work, but then I started passing my objects to functions with signatures like f(const Object& o), and suddenly the compiler barfed on a line in f such as o.GetAValue(), because I hadn't marked GetAValue as a const function. This can surprise you especially when you subclass something and don't mark your version of the virtual methods as const - in that case the compile could fail on some function you've never heard of before that was written for the base class.

(2) Avoid mutable variables when it's practical. A tempting trap can be to allow read operations to alter state, such as if you're building a "smart" object that does lazy or asynchronous i/o operations. If you can manage this with only one small mutable variable (like a bool), then, in my experience, this makes sense. However, if you find yourself marking every member variable as mutable in order to keep some operations const, you're defeating the purpose of the const keyword. What can go wrong is that a function which thinks it's not altering your class (since it only calls const methods) my invoke a bug in your code, and it could take a lot of effort to even realize this bug is in your class, since the other coder (rightly) assumes your data is const because he or she is only calling const methods.

Tyler
A: 

const has a funny way of propagating through your code. Thus, it's a really good idea to start using const as early and as often as possible. Deciding to start const-ifying your code late in the game can be painful (easy, but annoying).

Additionally, you will easily run into problems if methods that should be const aren't! This will creep through the code as well, and make it worse and worse.

MP24