🔒 Locked
const correctness
Advertisement
Original Post
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
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!
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!
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
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?
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]
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).
quote: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'').
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).
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.
might as well be
And then copying and pasting isn''t so appealing.
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.
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(); }
};
Topic Locked
This topic has been locked by a moderator. New replies are not allowed.
Sign in to reply to this topic.
Advertisement