mardi 28 mai 2013

Const-Correctness .... with example.

Some of my friend have trouble with the terrible "const" keyword this morning
They have a class 'test', an instance of that class and they want to pass it through a function as 'const test*' parameter.

The question was: what 'const classname*' means ? and by the way what is the difference with 'const classname* const' ?

To answer, let create a 'test' class defined with 'const' and not const function:


class test
{
public:
test(){}
~test(){}

int DoConstOp() const { return 0;}
int DoNotConstOp() { return 0;}

};


And now we create different version of a method call 'process_blahblah' in which we will call the 2 test's function. Those method will take a object of type 'test' but with 4 different signature:

  • const test&
  • const test*
  • const test* const
  • test* const

And call the 4 method from a main:

process_as_const_ref(t);
process_as_const_ptr(&t);
process_as_const_ptr_const(&t);
process_as_ptr_const(&t);


And now have a look at their implementation. I put under comment the lines that doesn't compile (under VS'12 at least... but result looks correct regarding the C++ standard !) + error message.



void process_as_const_ref(const test& t)
{
t.DoConstOp();
//t.DoNotConstOp();//Cannot build: cannot convert 'this' pointer from 'const test' to 'test &'
}

void process_as_const_ptr(const test* t)
{
t->DoConstOp();
//t->DoNotConstOp(); //Cannot build: cannot convert 'this' pointer from 'const test' to 'test &'
(const_cast<test*>(t))->DoNotConstOp(); //trick
}

void process_as_const_ptr_const(const test* const t)
{
t->DoConstOp();
//t->DoNotConstOp();//Cannot build: cannot convert 'this' pointer from 'const test' to 'test &'
(const_cast<test* const>(t))->DoNotConstOp(); //trick remove the const on the class not on pointer
//t++;//but this you can't do : 't' : you cannot assign to a variable that is const
}

void process_as_ptr_const(test* const t)
{
t->DoConstOp();
t->DoNotConstOp();
//t++;//but this you can't do : 't' : you cannot assign to a variable that is const
}


So the answer is:
  • const test& or const test* declare the the test instance you use as const, thats why you cannot non-const method.
  • and with const test* const or test* const, the 2nd const keyword declare the pointer as const, it means that you cannot do any modification of the pointer value (ptr++ ptr = another ptr ...etc ...).
Note that using the "test* const" syntax may be confusing and useless as by default the pointer you get is a "copy" of the pointer you have in the caller !


Aucun commentaire :

Enregistrer un commentaire