tags:

views:

212

answers:

10

I've seen a lot of uses of the const keyword put after functions in classes, so i wanted to know what was it about. I read up smth at here: http://duramecho.com/ComputerInformation/WhyHowCppConst.html .

It says that const is used because the function "can attempt to alter any member variables in the object" . If this is true, then should it be used everywhere, because i don't want ANY of the member variables to be altered or changed in any way.

class Class2
{ void Method1() const;
  int MemberVariable1;} 

So, what is the real definition and use of const ?

+1  A: 

If this is true, then should it be used everywhere, because i don't want ANY of the member variables to be altered or changed in any way?

Well, no. Sometimes you do want instance methods to modify members. For example, any set method will obviously need to set variables, so it's not the case that you should put const everywhere. But if your object's state is totally immutable, first consider whether it might not be better to have no instances at all (i.e., a static class), and if that's not the case, then make everything const.

John Feminella
+2  A: 

The meaning is that you guarantee to clients calling a const function member that the state of the object will not change. So when you say a member function is const it means that you do not change any of the objects member variables during the function call.

mikelong
That's not quite true - observable behavior does not change, but member data can if marked `mutable`. This allows caching once-calculated results, for example.
David Thornley
It's even worse. If you have a pointer pointing to some data, the `const` behind a member function only guarantees that the pointer isn't changed, not the data it points to. Often, however, the data is considered to be part of the object's state. So, actually, that `const` only prevents a member function from changing the object's member data, not all of its state. It enforces bit-wise constness, not logical constness.
sbi
Indeed, it only enforces bitwise constness, and all bets are off when you set a member mutable. It's only really a hint to the compiler, mr Klatchko has a better explaination above.
mikelong
+2  A: 

It's quite unusual not to want to have any member variables changed, but if that's what your class requires, then you should make all your member functions const.

However, you probably do want to change at least some members:

class A {
  private: 
    int val;
  public:
    A() : val(0) {}
    void Inc() { val++; }
    int GetVal() const { return val; };
};

Now if I create two instances of A:

A a1;
const A a2;

I can say:

a1.GetVal();
a2.GetVal();

but I can only say:

a1.Inc();

trying to change the value of a constant object:

a2.Inc();

gives a compilation error.

anon
+2  A: 

Fantastic explanation here

gmcalab
+9  A: 

A const method can be called on a const object:

class CL2
{
public:
    void const_method() const;
    void method();

private:
    int x;
};


const CL2 co;
CL2 o;

co.const_method();  // legal
co.method();        // illegal, can't call regular method on const object
o.const_method();   // legal, can call const method on a regulard object
o.method();         // legal

Furthermore, it also tells the compiler that the const method should not be changing the state of the object and will catch those problems:

void CL2::const_method() const
{
    x = 3;   // illegal, can't modify a member in a const object
}

There is an exception to the above rule by using the mutable modifier, but you should first get good at const correctness before you venture into that territory.

R Samuel Klatchko
+1  A: 

What is a "const member function"?

kemiisto
+1  A: 

The const keyword used after a method indicate that this method doesn't modify the object on which it's called. This way, this method can be called on a const version of the object.

Mathieu Pagé
+2  A: 

const, when attached to a non-static class method, tells the compiler that your function doesn't modify the internal state of the object.

This is useful in two ways:

  • If you do write code that changes internal state in your const method, the compiler catches the error, moving a programming error from run-time to compile-time.
  • If client code calls a non-const method on a constant pointer, the compiler catches the error, ensuring the "chain of not changing things" is maintained.

Typically you want to declare all non-mutating non-static class methods as const. This allows calling code to use the const qualifier on pointers, and it helps catch mistakes.

Typical C++: you can declare a class member variable "mutable" and then change it even from a const method.

Ben Supnik
A: 

Others have answered the technical side of your question about const member functions, but there is a bigger picture here -- and that is the idea of const correctness.

Long story short, const correctness is about clarifying and enforcing the semantics of your code. Take a simple example. Look at this function declaration:

bool DoTheThing(char* message);

Suppose someone else wrote this function and you need to call it. Do you know what DoTheThing() does to your char buffer? Maybe it just logs the message to a file, or maybe it changes the string. You can't tell what the semantics of the call are by just looking at the function declaration. If the function doesn't modify the string, then the declaration is const incorrect.

There's practical value to making your functions const correct, too. Namely, depending on the context of the call, you might not be able to call const-incorrect functions without some trickery. For example, assume that you know that DoTheThing() doesn't modify the contents of the string passed to it, and you have this code:

void MyFunction()
{
  std::string msg = "Hello, const correctness";
  DoTheThing(msg.c_str());
}

The above code won't compile because msg.c_str() returns a const char*. In order to get this code to compile, you would have to do something like this:

void MyFunction()
{
  std::string msg = "Hello, const correctness";
  DoTheThing(msg.begin());
}

...or even worse:

void MyFunction()
{
  std::string msg = "Hello, const correctness";
  DoTheThing(const_cast<char*>(msg.c_str()));
}

neither of which, arguably, are 'better' than the original code. But because DoTheThing() was written in a const-incorrect way, you have to bend your code around it.

John Dibling
A: 

Although the majority of experts will promote the use of const or const correctness, you have to put some thought and not apply it indiscriminately. Interfaces and iterations are some places where const correctness may not be advisable.

Interfaces & const

The const at the end of the function says that the function will not alter member variables. However, an interface specifies rules that apply to all descendants. Some descendants may want to alter their data members which are not the same members as the interface class. Let us take for example a Visitor pattern ...

class Writer_Interface { virtual void write(const unsigned int & value) const = 0 ; // Should this fn be const? virtual void write(const std::string& value) const = 0; };

The above class declares an interface for objects that write values. A user can create different writers, such as for windows, command line, files, databases, etc. The host class will not have to be altered to sponsor different applications of writing.

class Sample { void write(Writer_Interface * p_writer) { if (p_writer) { p_writer->write(text_member); p_writer->write(number); } return; } std::string text_member; unsigned int number; };

The issue here with const is that the Sample class does not care if the writer modifies any of its members. The Sample class only demands that the variable passed to the writer is not modified.

Descendant classes of Writer may need to alter their variables. For example, a file writer may need to open or create a stream variable, which violates the definition of a const function as specified in the Writer interface. Other cases include initialization on demand or RAII. The resources are not acquired during the construction of the object, but when the first write method is called. I get around RAII and const by declaring the members as mutable.

Iteration and const

This is one of my sore spots. If I have a container class, such as Record, and I want to write a for_each method that applies a functor to each item in the record, I have to create two versions, one const and the other not const. A const method will use the Records const for_each method and a non-const method would use the non-const for_each method. The for_each algorithm is the same; the code can be the same, or different (such as using const_iterator vs. iterator on STL containers).

Thomas Matthews