views:

1362

answers:

5

What is the meaning of const in declarations like these? The const confuses me.

class foobar
{
  public:
     operator int () const;
     const char* foo() const;
};
+23  A: 

The const means that the method promises not to alter any members of the class. You'd be able to execute the object's members that are so marked, even if the object itself were marked const:

const foobar fb;
fb.foo();

would be legal.

See How many and which are the uses of “const” in C++? for more information.

Blair Conrad
The link appears broken.
Andy Brice
@gnud fixed it. Thanks @gnud - I was away from my convenient question-link-making GreaseMonkey script.
Blair Conrad
+2  A: 

These const mean that compiler will Error if the method 'with const' changes internal data.

class A
{
public:
    A():member_()
    {
    }

    int hashGetter() const
    {
        state_ = 1;
        return member_;
    }
    int goodGetter() const
    {
        return member_;
    }
    int getter() const
    {
        //member_ = 2; // error
        return member_;
    }
    int badGetter()
    {
        return member_;
    }
private:
    mutable int state_;
    int member_;
};

The test

int main()
{
    const A a1;
    a1.badGetter(); // doesn't work
    a1.goodGetter(); // works
    a1.hashGetter(); // works

    A a2;
    a2.badGetter(); // works
    a2.goodGetter(); // works
    a2.hashGetter(); // works
}

Read this for more information

Mykola Golubyev
+5  A: 

The const qualifier means that the methods can be called on any value of foobar. The difference comes when you consider calling a non-const method on a const object. Consider if your foobar type had the following extra method declaration

class foobar {
  ...
  const char* bar();
}

The method "bar" is non-const and can only be accessed from non-const values.

void func1(const foobar& fb1, foobar& fb2) {
  const char* v1 = fb1.bar();  // won't compile
  const char* v2 = fb2.bar();  // works
}

The idea behind const though is to mark methods which will not alter the internal state of the class. This is a powerful concept but is not actually enforcable in C++. It's more of a promise than a guarantee. And one that is often broken and easily broken.

foobar& fbNonConst = const_cast<foobar&>(fb1);
JaredPar
You got it backwards: const methods can be called on non-const objects, but non-const methods can't be called on const objects. And that you can break const if you really want to isn't a good argument against it. You can break most "guarantees" by casting maliciously.
sth
@sth, I really need to change my morning routine to be 1) finish coffee then 2) open up SO. Right now I mix and match the two. I've updated the post to reflect the actual behavior
JaredPar
I thought the answer is about other const methods and not about const objects.
Mykola Golubyev
+4  A: 

Blair's answer is on the mark.

However note that there is a mutable qualifier which may be added to a class's data members. Any member so marked can be modified in a const method without violating the const contract.

You might want to use this (for example) if you want an object to remember how many times a particular method is called, whilst not affecting the "logical" constness of that method.

Alnitak
+2  A: 

When you add the const keyword to a method the this pointer will become const, and you can therefore not change any member code. (Unless you use mutable, more on that later).

The const keyword is part of the functions signature which means that you can implement two similar methods, one which is called when the object is const, and one that isn't.

#include <iostream>

class ConstClass
{
private:
    int counter = 0;
public:
    void Foo()
    { 
     std::cout << "Foo" << std::endl; 
    }

    void Foo() const
    {
     std::cout << "Foo const" << std::endl;
    }

};

int main(void)
{
    ConstClass* cc = new ConstClass();
    const ConstClass* ccc = cc;
    cc->Foo();
    ccc->Foo();
    delete cc;
    ccc = null;
    return 0;
}

This will output

Foo
Foo const

In the non-const method you can change the instance members, which you cannot do in the const version. If you change the method declaration in the above example to the code below you will get some errors.

void Foo()
    {
     counter++; //this works
     std::cout << "Foo" << std::endl; 
    }

void Foo() const
    {
     counter++; //this will not compile
     std::cout << "Foo const" << std::endl;
    }

This is not completely true, because you can mark a member as 'mutable' and a const method can then change it. It's mostly used for internal counters and stuff. The solution for that would be the below code.

#include <iostream>

class ConstClass
{
private:
    mutable int counter;
public:

    ConstClass() : counter(0) {}

    void Foo()
    {
     counter++;
     std::cout << "Foo" << std::endl; 
    }

    void Foo() const
    {
     counter++;
     std::cout << "Foo const" << std::endl;
    }

    int GetInvocations() const
    {
     return counter;
    }
};

int main(void)
{
    ConstClass* cc = new ConstClass();
    const ConstClass* ccc = cc;
    cc->Foo();
    ccc->Foo();
    printf("The ConstClass instance has been invoked %d times\n",
           ccc->GetInvocations());
    delete cc;
    ccc = NULL;
    return 0;
}

which would output

Foo
Foo const
The ConstClass instance has been invoked 2 times
Mats Fredriksson