Skip to main content
gamedev.net
🔒 Locked

const correctness

Started by Qw3r7yU10p! 14 replies 3.1k views
Original Post
Qw3r7yU10p!
Qw3r7yU10p!
I''ve just been going through some old code making a few changes. I''ve made a few things const . I''ve changed one thing and it has meant I''ve had to change about 60 functions in 15 files. I wish I hadn''t bothered! Actually I don''t really as it''s got me thinking about the way things have been structured in general. Does anyone have good ideas for how to control the knock-on effect or opinions on how to do it correctly? Or perhaps documents? I know the gotw stuff but the far reaching consequences weren''t explained. ''All we are saying is "Give Peace a Chance"'' - John Lennon/Yoko Ono
daerid
daerid
A couple of good rules of thumb to follow would be:

1) ANY member function which doesn''t alter the members of the class should be marked as const.
2) If the member function returns a reference to a member, make it const. If you need to be able to change it, make a duplicate member function that doesn''t return a const reference and isn''t marked as const.
3) Anything larger than a 32-bit argument should be passed as a const reference.
4) Some people say you should pass ALL arguments/parameters as const, and just make a copy if you need to alter it. This is something to think about, but usually isn''t necessary for small values.
5) And the simplest rule: If it shouldn''t be changed, make it const!
daerid@gmail.com
Rick Scott
Rick Scott
I went through the same thing as yourself a couple months ago. But I also changed from "using namespace std;" to fully-qualified std:: names. All I thought to do was just thank my lucky stars that my compiler was so good at figuring out which parts I needed to change. I had to click on each individual error and change it manually, but in the end I was a happy camper
civguy
civguy
You can also read this large thread about people''s opinions on whether it''s worth it or not.
Koen
Koen
quote:
Original post by daerid
5) And the simplest rule: If it shouldn''t be changed, make it const!

This rule is giving me trouble. Suppose you have this class:

class Something {
public:
SomeType* pointer_to_sometype;

void setMember(const SomeType* constargument) {
pointer_to_sometype=constargument;
}
};

This won''t compile because constargument is assigned to a non-const-pointer. I can see why (I''m not doing it here, but you would be able to change what is pointed to through pointer_to_sometype). const_cast would be a solution, as would be making constargument non-const. Is there a better solution for this?
lmov
lmov
quote:
This won't compile because constargument is assigned to a non-const-pointer

You are mistaking a pointer to a const object with a const pointer to a non-const object. 'int*' is a non-constant pointer to a non-constant int; 'const int*' is a non-constant pointer to a constant int; 'int* const' is a constant pointer to a non-constant int; and 'const int* const' is a constant pointer to a constant int. So in your example, change void setMember(const SomeType* constargument) to void setMemeber(SomeType* const constargument).

- lmov

[edited by - lmov on May 30, 2003 2:47:29 PM]
lmov
Koen
Koen
setMember is not supposed to change what it''s argument points to. So the object pointed to by constargument should not change while setMember executes. It should change at a later time, though. That''s why pointer_to_sometype can''t be const. So both solutions are not what I need.
Koen
Koen
quote:
Original post by Anonymous Poster
Wouldn't that be SomeType const *?

const int * x;
and
int const * x;
are the same thing. They mean you cannot do
x->someNonConstMember();
int * const x;
means you cannot do
x=0;
for instance.



[edited by - Koen on May 30, 2003 3:25:04 PM]
Koen
Koen
AP and lmov, what you suggest would mean constargument cannot be changed. This is an adress. I would be able to do everything I want with the SomeType-object it points to. That is not what I want to do. I want the heading to say setMember will not change the object used, through the pointer. I don''t really care about the pointer (saying the pointer is const, would be something like saying an int or float argument is const).
Extrarius
Extrarius
quote:
Original post by Koen
AP and lmov, what you suggest would mean constargument cannot be changed. This is an adress. I would be able to do everything I want with the SomeType-object it points to. That is not what I want to do. I want the heading to say setMember will not change the object used, through the pointer. I don''t really care about the pointer (saying the pointer is const, would be something like saying an int or float argument is const).
You said you need to change the data being pointed to later though. The way you have it now is saying "I will not change what is being pointed to" but then you change your mind by copying the address to a place that would let you change what is being pointed to. You should only do it that way if you intend to never change what is being pointed to (and in that case you should change the type of ''pointer_to_sometype'').
"Walk not the trodden path, for it has borne it's burden." -John, Flying Monk
Koen
Koen
Ok, that's what I really needed to know. I thought a const-argument only shouldn't be changed inside the function/member-body, and that what happens with the "thing it points to", doesn't matter outside the body.
Thanks

[edited by - Koen on May 30, 2003 4:15:05 PM]
Qw3r7yU10p!
Qw3r7yU10p!
Okay, apart from people who don''t know what const does and haven''t read the articles I linked to - does anyone else have suggestions for tackling the knock on effect of making member functions const?

I seem to have had to come up with two versions of the same function. The bodies of the function are ''the same'' although actually what is being done is the const versions of functions are being called. So really the functions are completely different. Overloading functions or using const is just a shorthand way of saying ''this is a completely different function''.

I don''t like having duplicated code (ie two functions with essentially the same code), but really they''re not the same at all. I might as well call the const version of Foo constFoo to emphasise the difference. Really the code isn''t duplicated except for all the parts in the body of a function that are separate to function calls. Maybe I should move those into separate functions and re-use the common code.


struct A {
void B() const {}
void B() {}
void C() const {
B(); //calls B() const

}
void C() {
B(); //calls B()

}
};

might as well be

struct A {
void B() const {}
void D() {}
void C() const {
B();
}
void C() {
D();
}
};

And then copying and pasting isn''t so appealing.
JohnBolton
JohnBolton
quote:
Original post by petewood
I seem to have had to come up with two versions of the same function. The bodies of the function are ''the same'' although actually what is being done is the const versions of functions are being called. So really the functions are completely different. Overloading functions or using const is just a shorthand way of saying ''this is a completely different function''.

I don''t like having duplicated code (ie two functions with essentially the same code), but really they''re not the same at all. I might as well call the const version of Foo constFoo to emphasise the difference. Really the code isn''t duplicated except for all the parts in the body of a function that are separate to function calls. Maybe I should move those into separate functions and re-use the common code.



Sometimes you can''t cut and paste because the const version might apply the const keyword differently in the body of the function. Here''s how I avoid duplicating code. It usually works but it is annoying C++ voodoo and it assumes that the const and non-const functions do the same thing:

struct A
{
void B() const {}
void B() { const_cast< A const * >( this )->B(); }
void C() const { B(); }
void C() { const_cast< A const * >( this )->C(); }
};

John BoltonLocomotive Games (THQ)Current Project: Destroy All Humans (Wii). IN STORES NOW!

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.