Archived

This topic is now archived and is closed to further replies.

amish1234

question about const

Recommended Posts

Doc    586
"int blah() const" has to be a member of some class. The const means that the function won''t modify the contents of the object on which it operates.

Share this post


Link to post
Share on other sites
Nypyren    12065
say you have an operator+ for a complex number class...

Complex a, b, c;
c = a+b;

a and b aren''t modified. a''s method operator+ returns a temp object that gets assigned to c. operator+ (...) const is used to signify that the function won''t modify a''s member variables. I forget exactly when this is required...

Share this post


Link to post
Share on other sites
Doc    586
quote:
Original post by Nypyren
I forget exactly when this is required...


Say you have a constant that gets promoted to your class. Eg. a string:

string a = " world";
string x = "hello" + a;

"hello" would be promoted to a constant string type, so operator+ must be a const member.

Image loads when I''m online!The following statement is true. The previous statement is false.
Shameless promotion:
FreePop: The GPL Populous II clone.

Share this post


Link to post
Share on other sites
31337    100
Is it valid for a const function to return a reference to a member variable and then have the reference edited outside of the function?

Share this post


Link to post
Share on other sites
Wildfire    154

MyClass& MyClass::returnObject(void)const //WRONG

{
return(*this);
}
// error C2440: 'return' : 'const class MyClass' cannot be

// converted to 'class MyClass &'.


const MyClass& MyClass::returnObject(void)const //RIGHT

{
return(*this);
}


If you would be allowed to return a non-const reference your data could be modified despite the member function being const. Thus it's not legal.

[edited by - Wildfire on August 8, 2003 3:09:48 AM]

Share this post


Link to post
Share on other sites
civguy    308
Wildfire, here''s something that''ll surprise you:


struct T {
T(int& b) : a(b) {}
int& a;
int& getA() const {
return a;
}
};

int main() {
int x = 4, y = 8;
const T t(x); //note: t is const.
cout << t.a << '','';
t.getA() = y;
cout << t.a;
}

Compiles OK, output is: 4,8

Share this post


Link to post
Share on other sites
foofightr    130
civguy, that''s not the same thing. Wildfire is returning (*this) which is a const variable, so the function''s return type has to be const as well. Your member variable ''int a'' is not const, and you do not modify it inside getA(), so all is well. Also it doesn''t matter that t is const, because you are not [directly] modifying it, you are using an accessor function.

Share this post


Link to post
Share on other sites
civguy    308
quote:
Original post by foofightr
civguy, that''s not the same thing.
It''s not the same thing Wildfire posted, but it''s the thing in which Wildfire tried to come up with a counterargument:
> Is it valid for a const function to return a reference
> to a member variable and then have the reference edited
> outside of the function?
quote:
Your member variable ''int a'' is not const, and you do not modify it inside getA(), so all is well.

This works too:

struct T {
T(int& b) : a(b) {}
int& a;
void setA(int& b) const {
a = b; //modified inside
}
};

int main() {
int x = 4, y = 8;
const T t(x); //note: t is const.
cout << t.a << '','';
t.setA(y);
cout << t.a;
}

Ignore the fact it''s now setA, not getA
quote:
Also it doesn''t matter that t is const, because you are not [directly] modifying it, you are using an accessor function.
That''s not really the trick in the example, as shown above. I''m not actually modifying ''t''. I''m modifying the memory where t.a points to. At the end of the example, x == y == 8.

Share this post


Link to post
Share on other sites
SpaceRogue    122
civguy, that's a neat trick.
I would've bet that wouldn't work.
I assume the entire reason is because 'a' is a reference to an integer 'x' that is not a member variable and which existed before the constant class instance 'T' existed?

(Edited last sentence for clarity.)

[edited by - SpaceRogue on August 8, 2003 5:42:25 PM]

Share this post


Link to post
Share on other sites
rypyr    252
struct T {
int* p;
int& r
void setP(int* _p) const { p = _p; } // Illegal
void setR(int& _r) const { r = _r; } // Legal???
};

I think it's kinda stupid. If you consider references are "almost like" pointers, then you really are modifying what the reference points to (analagous to changing the value of the pointer variable). Thus, I feel it shouldn't be allowed.

My philosophy on the matter is that a member variable's VALUE shall not be allowed to change inside a const member function. But a reference variable's VALUE is tricky to define: Is the value of a reference 1) the value of what it points to (i.e. the integer value) or 2) what it points to (i.e the integer variable). I guess C++'s answer is the first, but even if that's the case, if you are changing what a reference points to you are MORE THAN LIKELY changing both (i.e. the variable and the value).

I feel it shouldn't be allowed, but that's just my two cents...does this buy you anything?

Regards,
Jeff

[edited by - rypyr on August 8, 2003 6:02:58 PM]

Share this post


Link to post
Share on other sites
SpaceRogue    122
p = _p may be illegal, but *p = *_p isn't even if p and _p are const pointers (not pointers to const!).

I suppose this happens with references because what is commonly called a constant reference is really a reference to constant data. Something like int& const r which is normally meaningless, seems to be how a reference member of a const object is treated.

It seems as if when you declare a constant object of a class, members get a const tacked on the end:

int i becomes int const i
int* p becomes int* const p // *p can still be modified.
int& r becomes int& const r // r can still be modified.

Weird.

[edited by - SpaceRogue on August 8, 2003 6:15:48 PM]

Share this post


Link to post
Share on other sites
JD    208
A reference is always associated with only one object. You can''t make it point to another object. You can''t do:

int& r = new int(5);
r = new int(7);

however you can do:

int b = 6;
int &r = b;// b&r are same
r++;
cout << b << endl;

which will print 7 thru b object.

if you do:

const int &r = b;
r++;// can''t because it''s constant

but you can do:

b++;// b isn''t constant

Interestingly you can''t do:

int &r = 7;

so you must write it as:

const int &r = 7;
r++;// error, r is constant

There are whole bunch of other C++ rules that make the lang. exhaustive.

Share this post


Link to post
Share on other sites
Wildfire    154
civguy: Yes, it is surprising at first, but if you give it a little thought you will notice that it doesn't contradict my rule in any way.

If a member function is const you cannot modify any of the classes member-variables (unless defined as 'mutable'), and you must not return them in a way that would allow the user of your class to modify them.

However: your 'int& a' is a reference, and can as such not be modified (the refernece, not the date being refered to). And as long as 'a' is pointing to data outside your class (which is not const) you are not violating said rule.

You could say 'int& a' is the same as 'int* const a' (if you disregared the . vs -> syntax).

Edit: const int* / int* const confusion... damn syntax

Edit2:

However, this works too... which it should not. Guess it's too sneaky for the compiler to notice.

struct T {
int& a;
int c;

T (void) : a(c) {};

int& getA (void) const;
};

int& T::getA(void) const
{
return(a);
}


[edited by - Wildfire on August 9, 2003 10:52:13 AM]

Share this post


Link to post
Share on other sites