Omgili, forum search, forums search, search forums, discussion search,discussions search, search discussions, board search, boards search, search boards
  Advanced Search

What's the philosophical definition of const? Organization: SunSITE.dk - Supporting Open source

On Tue, 21 Apr 2009 10:44:39 CST, DeMarcus <...@tellus.orb.sunsite.dk

Is there any common idea of the _philosophical_ definition of const or
is this very individual in the business? What is your opinion on this?

To explain what I mean I give this example:

class CarFactory
{
void addCarPrototype( Car* car, string carType ) const;

void setCarTypeToManufacure( string carType );

Car* createCar() const;
}

Here addCarPrototype is a const function in my eyes. It will for sure
alter bits and bytes within CarFactory but in my philosophical meaning
it doesn't alter the object CarFactory.

Here is another example.

class Boat
{
void boardPassenger( Passenger* passenger ) const;

... a lot of other functions belonging to a boat ...
}

I add passengers to the boat but they don't alter my boat (hopefully).

Is there a common way of thinking that can be good to know when dealing
with these kind of const structures or is it up each and everyone and
their perspectives of the objects? Or if I put it like this; if you
hired me and I would write const code like the above, would you react?

/Daniel

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]



On Tue, 21 Apr 2009 20:20:23 CST, "Bo Persson" <...@gmb.dk

It depends on what the rest of the interface is like. The number of
passengers might very well alter the state of the boat. Can it have
any number of passengers on board, or is there a regulated maximum
allowed?

Is an overloaded boat the same as an empty boat?

I'm not hiring. :-)

Bo Persson

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

On Tue, 21 Apr 2009 20:22:35 CST, Thomas Richter <...@math.tu-berlin.de

In this particular case, I would say "no". Even if you use the metaphor
of a "real" car factory, introducing a new car model implies
reconfiguring the work in the factory, so it changes. However, it's not
always (though often) useful to think in such metaphors. Rather think in
the "state" of the object, and what this object is supposed to
represent. If the represented "state" changes (for the matter of the
program, not in a metaphor), make it non-const.

Probably a wrong use of the metaphor. If the "state" of the boat encodes
the number of passengers on it, then boarding the boat changes its
state, and so it is non-const.

That is, I would make a method const if the *observable* behavior of the
class does not change; that is, if there is no way to determine from
outside whether the internal wirings of the class changed. That is, if
your boat can return a list or count of passengers, then the state
changes by the boarding procedure, and the method should be non-const.

If just the internal administration of the object changes somehow, but
there is no way to make this change apparent to the outside, make it
const. For example, a list could have a method that returns the number
of the objects it contains. It might make sense if the list only changes
occasionally to buffer this value, and only re-compute it when it is no
longer up to date. This recomputing could happen in the "element
counter". Even though this "size" method of the class would change some
members of an object of this class, it doesn't change the visible state
of the object, and thus the method should be "const".

I'd say the above usage of "const" is rather common, and I would
recommend using it that way.

I would say that you're stretching the metaphor too far.

So long,
Thomas

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

On Tue, 21 Apr 2009 20:47:03 CST, "mar...@gmail.com" <...@gmail.com

On Apr 21, 6:44 pm, DeMarcus <...@tellus.orb.sunsite.dk
Being a C++ list I can say what Stroupstrup says in the TC++PL book:
"It indicates that these functions do not modify the state of a Date."
In that case Date was the class with some of its member functions
defined as "const".
I agree with Stroupstrup: const indicates to the user of the class
that calling that method not state modification occurs.
In my experience the only cases where I wrote a const method that
modified the internal state of a class were for lazy calculation.
E.g.:
--- [snip] ---
class my_class
{
private: mutable double _stats;
private: mutable bool _stats_computed;
//...
public: double stats() const
{
if (!this- {
// a very heavy-load computation
// for computing stats
this- this- }
return this- }
};
--- [snip] ---

call to addCarPrototype, the factory is able to create another kind of
car (i.e., the one just inserted). So its capabilities are increased.

You haven't altered your boat as shape but you have altered it in
passengers capacity: after boardPassenger the object is able to accept
only N-1 passengers (assuming its capacity was N just before the call
to boardPassenger).
So in my opinion the state of the object has changed.

Cheers,

-- Marco

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

On Tue, 21 Apr 2009 20:47:51 CST, Mathias Gaunard <...@gmail.com

On 21 avr, 18:44, DeMarcus <...@tellus.orb.sunsite.dk

Then it's ok.
What mutability means for your object is up to you to define.

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Anonymous Wrote:

On Apr 21, 5:44 pm, DeMarcus <...@tellus.orb.sunsite.dk
How about this explanation:

In this case we are dealing with two different levels of abstraction.

Boat and boat-with-people and hence need to represent these in
separate classes.

class Boat
{
// members
};

class BoatWithPeople
{
void boardPassenger( Passenger* passenger ); // board pBoat
private:
const Boat _Boat; // never modified
int _NumPeople; // modified upon boarding
// other members such as revenues on boat trip which never are part
of Boat
};

Your BoatWithPeople is no longer a const when boarding, but yout boat
still is.

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

On Tue, 21 Apr 2009 20:41:13 CST, Pavel Minaev <...@gmail.com

On Apr 21, 9:44 am, DeMarcus <...@tellus.orb.sunsite.dk
Any specific reason why it's not "const Car* car" here?

But of course it does. If, after calling your addCarPrototype(), the
behavior of your object suddenly changes, then the function I called
wasn't really "const".

You make the (often occured) mistake of literally mapping real-world
entities onto objects. An instance of "Boat" class is not the same
thing as a boat. It is a model for a boat, yes, but that's different.

See above. Basically, a true const function should not change the
behavior of the receiver for any consequent attempts to interact with
it in any way (using public interfaces, of course). In particular, I
should be able to call a const function on the same receiver object
several times in a row, without any observable differences _for that
object_ (it obviously can change state of non-const objects referenced
via arguments).

A corner case here is when the bevahior of receiver object actually
depends on the state of objects that are mutated by a const function
via its (non-const) arguments. A more specific case is when const
function receives "this" also as one of its non-const arguments, and
mutates that. Those are exceptions, but I hope the gist of this not
very formal definition is clear.

Looking at the code above, I'd say you're a Java developer :)

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

On Wed, 22 Apr 2009 16:49:21 CST, DeMarcus <...@hotmail.com

No, I just missed that.

Thanks for all input all of you, it was helpful. My summary is this:

A function may be declared const if the observable behavior or state
does not change, i.e. multiple calls to a const function should give the
same result, e.g. if using a const function would avoid a thrown
exception in a successoral function call to the same object then it's
not a const function.

Hehe. Right on target. Actually I was a promising C++ programmer once
and I'm working hard to get back there. :)

PS. Excuse the "Organization: SunSITE.dk..." banner. I can't remove it
since I use this free of charge news groups service provider.

{ Well, it would be nice if you at least could remove quoted clc++m banners.
Free newsservers include AIOE and Mozarella (I'm sorry but Google failed to turn
up the one I seem to remember, at U. of Aarhus). Quoted banner removed. -mod }

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

On Thu, 23 Apr 2009 15:26:34 CST, Bart van Ingen Schenau <...@ingen.ddns.info

That is a reasonable summary.
To put it in one sentence: Calling or not calling a const member
function does not affect the behaviour of (the other member functions
of) the object.

<snip
To the mods: It would also be nice if the conventional sig-marker of
"-- \n" would be used for the banner (currently, the space is missing).
That would make it easier for newsreaders to automatically remove the
banner.

Bart v Ingen Schenau
--
a.c.l.l.c-c++ FAQ: http://www.comeaucomputing.com/learn/faq
c.l.c FAQ: http://c-faq.com/
c.l.c++ FAQ: http://www.parashift.com/c++-faq-lite/

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

On Tue, 21 Apr 2009 20:48:18 CST, restor <...@interia.pl

Hi,
Yes I, in fact, would react to it. Let me explain why.

First, the name of the keyword 'const' in C (and hence in C++) was an
effect of a compromise and the original proposal was to use a name
'readonly'. (I read it in "The Design and Evolution of C++"). If you
look at 'const' this way, saying that you will alter bits and bytes
means that it is not a readonly method.

If there is a common idea of what 'const' means, it is that calling a
const method will not change the object's behavior. In your example
(if I got your intention correctly), if I call:

carFactory.setCarTypeToManufacure( "Picassa" );
return carFactory.createCar();

without registering a prototype "Picassa" with addCarPrototype, either
one of those functins will throw an exception, or the latter will
return NULL. Whereas if I call

carFactory.addCarPrototype( &picassa, "Picassa" );

before, I will have no exception or NULL. This means that
addCarPrototype changes the behavior of carFactory and hence should
not be const (even if it is possible to implement it as const).

In this example I can understand why you say that boardPassenger
doesn't alter the boat, but I believe that passengers themselves
shouldn't be stored in class Boat. A more natural solution for me
would be:

class Boat
{
... a lot of other functions belonging to a boat ...
};

class BoatComplement
{
Boat const& boat;
vector<const Passenger*
void boardPassenger( Passenger* passenger ); // non-const
};

Regards,
&rzej

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

On Wed, 22 Apr 2009 16:49:22 CST, Francis Glassborow <...@btinternet.com

Oh, but C++ had const first and then it was borrowed by C and the
meaning was subtly changed.
In C++ const really does have 'immutable' as one of its meanings but it
also carries the meaning of immutable in the local context. That is why
we have to distinguish between 'logically const objects' and 'physically
const' ones.

void foo(int const & icr);
Now in the scope of foo the object referred to by icr is treated as
readonly and the compiler is allowed to assume that the underlying
object is not changed by a call to foo().

void bar(int & ir);
calls to bar may change the object being passed to it.

int main(){
int i(5); // current value 5 but can be changed
int const ic(5); // value 5 throughout the program
foo(i); // foo does not change it
bar(i); // compiler must assume that i may longer be 5 on return
foo(ic); // OK
bar(ic); // error
foo(5); // OK
bar(5); // error
}

Note that in the scope of main ic is effectively a named literal but in
the scope of foo() icr is a readonly variable.
The compiler can replace all uses of ic with its value and can place ic
in ROM if it wants to provide storage for it.

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

On Thu, 23 Apr 2009 08:08:50 CST, restor <...@interia.pl

This is a bit different from what I have learned so far about C++. If
I have a function:

void doSomething( const int & I );

void myFun( const int & I )
{
// before
doSomething( I );
// after
}

Can I assume that "I" has the same value at points "before" and
"after"? What If I use it like:

int counter = 0; // a global

void doSomething( const int & I ) {
++counter;
}

int main() {
myFun( counter );
return 0;
}

I am quoting an example I found somewhere in this (or comp.lang.c++)
forum.

Regards,
&rzej

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

On Thu, 23 Apr 2009 19:54:10 CST, Francis Glassborow <...@btinternet.com

Yes that is a problem with any language that supports aliasing along
with global variables. However the problem does not lie with references
but with the evils of globals.

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Anonymous Wrote:

On Apr 21, 9:44 am, DeMarcus <...@tellus.orb.sunsite.dk
I think there was a slightly important part of const which was missed
in all of the posts thus far. People call it const correctness. For
example,
void foo(T const * x);
This means that good-style-wise, barring some other way to access *x
available to foo, the function shall not modify *x. The rest of the
posts have talked about what it means to modify, but they did not
address specifically what it means to have a pointer to const or
reference to const, aka const correctness.

Take the following class:
class T
{ void set(int y) { x = y; }
int get() const { return x; }
int * getIntPtr() const { return & x; }
private:
int x;
};

That class doesn't obey what most people call const correctness. If
you pass a pointer to T to foo, foo could modify the T object. The
getIntPtr method does \not\ modify the state of the object, and thus
the compiler allows you to define the function as const. However, the
function getIntPtr does allow a point of access for modification, thus
breaking const correctness.

When determining if a member function should be const or not, const
correctness dictates that one should not just look at whether the
function modifies the object, but also whether it allows a
modification. I think the simplest way of phrasing const correctness
is:

If you have a pointer to an object or a reference to an object, and no
other way to access that object besides that pointer / reference, then
you should not be able to modify that object short of a cast. This is
const correctness.

The compiler will not enforce const correctness. It requires some work
by the user. However, if you define your class properly:
class const_correct_T
{ void set(int y) { x = y; }
int get() const { return x; }
int * getIntPtr() { return & x; }
int const * getIntPtr() const { return & x; }
private:
int x;
};
then the compiler \will\ enforce const correctness. For a const
correct class, the compiler will ensure that code cannot modify an
object if given only a pointer to const or reference to const which
points to the object (assuming no casting away constness).

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]