C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

overriding constant member functions

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ language, library and standards
View previous topic :: View next topic  
Author Message
Køi¹tof ®elechovski
Guest





PostPosted: Fri Oct 06, 2006 1:01 am    Post subject: overriding constant member functions Reply with quote



In the following code, CC remains an abstract base class because
IC::foo(void) const remains unimplemented:
class IC { virtual void foo() const = 0; }; class CC { int m_x; void foo()
{ this->m_x = 0; }};
In order for CC::foo to override IC::foo, it must be declared as void foo()
const.
However, we cannot do that because this->m_x would be inferred constant.
I do not find this extension of constance justified.
If CC::foo overrides IC::foo,
it must treat this as a pointer to a constant object of class IC, in that no
member of class IC may be modified;
on the other hand, it is unreasonable to prohibit it from modifying
noninherited members of class CC.
Generally speaking,
if a function takes a reference to a constant object,
it should be expected
that the function does not modify the members of the object that belong to
its _declared_ type;
it should not be inferred that all members of the actual type of the object
remain unmodified.
Such an inference is mandatory under the current standard.
Am I right or wrong? Is this suggestion ontologically acceptable?
In case I am wrong,
I wonder whether declaring a constant abstract virtual member function
should be disparaged.
Especially when the function belongs to an interface class.
Otherwise the implementor of the interface has three choices:
declare his private data that must be modified as mutable (too permissive),
access them via an internal pointer
(remember the latest discussion about leaking modifiable objects in the
constructor?) (uses unnecessary memory)
or use const_cast in the overriding implementation (clumsy).
Neither solution seems to be good. What do you think?
Chris


---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Back to top
Greg
Guest





PostPosted: Fri Oct 06, 2006 4:56 pm    Post subject: Re: overriding constant member functions Reply with quote



On Oct 5, 1:01 pm, giecr...@stegny.2a.pl ("Køi¹tof ®elechovski") wrote:
Quote:
In the following code, CC remains an abstract base class because
IC::foo(void) const remains unimplemented:
class IC { virtual void foo() const = 0; }; class CC { int m_x; void foo()
{ this->m_x = 0; }};
In order for CC::foo to override IC::foo, it must be declared as void foo()
const.

I think a better approach for implementing CC::foo() const would be to write
a const method for it - rather then rename one of CC's non-const methods()
in an attempt to pass it off as CC::foo() const. Frankly, it is hard to see
how CC::foo()'s current implementation could be considered at all const.

Quote:
However, we cannot do that because this->m_x would be inferred constant.

A method's const qualifier guarantees that calling the method will not
change the object's "value" or state. Now assigning zero to one of the
object's data members certainly appears like a change is being made to the
object's state. Presumably, the value of m_x means something to the
implementation of CC and that a change to its value would be detectable by
the client. If that is the case, then foo() is neither const nor does it
override CI's abstract foo() const method. The programmer needs to use a
different function.

Quote:
I do not find this extension of constance justified.

But whoever designed CI's interface must feel otherwise. The foo method
would not be declared const unless the designer thought it is reasonable to
require that every derived class of CI, implement foo() in a const way.
Since we have no way of knowing what foo() is supposed to do or what the
data member m_x represents, we have no way of evaluating whether this
requirement seems at all reasonable or not. If the const requirement is not
reasonable than IC should declare the method as non-const - it's not
necessary to change the language to fix that kind of problem.

Quote:
If CC::foo overrides IC::foo,
it must treat this as a pointer to a constant object of class IC, in that no
member of class IC may be modified;
on the other hand, it is unreasonable to prohibit it from modifying
noninherited members of class CC.

Any change to any of the object's members is potentially a change to the
object's value - and therefore requires a non-const object. It's up to the
programmer, and not the language, to decide which members contribute to the
object's value and which do not. And it's far better for the language to
assume that all members are significant instead of just some of them. In
fact by what means would a programmer under these new rules recreate the
current behavior in which all members are treated alike when evaluating the
constness of an operation?

Quote:
Generally speaking,
if a function takes a reference to a constant object,
it should be expected
that the function does not modify the members of the object that belong to
its _declared_ type;

Declared where? And what members of an object would a function be modifying
if not the members of the object's declared type? What other members would
there be?

Quote:
it should not be inferred that all members of the actual type of the object
remain unmodified.

An object has just one value - that is, just one state at any one time.
Granted not all clients of a polymorphic object may be able to observe its
state to the degee as other clients, but that is not to say that the object
ever has more than a single state.

Quote:
Such an inference is mandatory under the current standard.
Am I right or wrong?  Is this suggestion ontologically acceptable?

It sounds as if the goal is for the object to hold multiple values - the
constness of each could then be individually adjustable. If that is the
goal, then inheritance is not the right pattern. Instead the object should
use composition - instead of inheriting from IC, CC would have an IC data
member. in that way the constness of the CC object and the constness of the
CC object could be maintained in a more autonomous manner.

Greg

---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Back to top
Greg Herlihy
Guest





PostPosted: Fri Oct 06, 2006 6:05 pm    Post subject: Re: overriding constant member functions Reply with quote



On Oct 5, 1:01 pm, giecr...@stegny.2a.pl ("Køi¹tof ®elechovski")
wrote:
Quote:
In the following code, CC remains an abstract base class because
IC::foo(void) const remains unimplemented:
class IC { virtual void foo() const = 0; }; class CC { int m_x; void foo()
{ this->m_x = 0; }};
In order for CC::foo to override IC::foo, it must be declared as void foo()
const.

I think a better approach for implementing CC::foo() const would be to
write a const method for it - rather then rename one of CC's non-const
methods() in an attempt to pass it off as CC::foo() const. Frankly, it
is hard to see how CC::foo()'s current implementation could be
considered at all const.

Quote:
However, we cannot do that because this->m_x would be inferred constant.

A method's const qualifier guarantees that calling the method will not
change the object's "value" or state. Now assigning zero to one of the
object's data members certainly appears like a change is being made to
the object's state. Presumably, the value of m_x means something to the
implementation of CC and that a change to its value would be detectable
by the client. If that is the case, then foo() is neither const nor
does it override CI's abstract foo() const method. The programmer needs
to use a different function.

Quote:
I do not find this extension of constance justified.

But whoever designed CI's interface must feel otherwise. The foo method
would not be declared const unless the designer thought it is
reasonable to require that every derived class of CI, implement foo()
in a const way. Since we have no way of knowing what foo() is supposed
to do or what the data member m_x represents, we have no way of
evaluating whether this requirement seems at all reasonable or not. If
the const requirement is not reasonable than IC should declare the
method as non-const - it's not necessary to change the language to fix
that kind of problem.

Quote:
If CC::foo overrides IC::foo,
it must treat this as a pointer to a constant object of class IC, in that no
member of class IC may be modified;
on the other hand, it is unreasonable to prohibit it from modifying
noninherited members of class CC.

Any change to any of the object's members is potentially a change to
the object's value - and therefore requires a non-const object. It's up
to the programmer, and not the language, to decide which members
contribute to the object's value and which do not. And it's far better
for the language to assume that all members are significant instead of
just some of them. In fact by what means would a programmer under these
new rules recreate the current behavior in which all members are
treated alike when evaluating the constness of an operation?

Quote:
Generally speaking,
if a function takes a reference to a constant object,
it should be expected
that the function does not modify the members of the object that belong to
its _declared_ type;

Declared where? And what members of an object would a function be
modifying if not the members of the object's declared type? What other
members would there be?

Quote:
it should not be inferred that all members of the actual type of the object
remain unmodified.

An object has just one value - that is, just one state at any one time.
Granted not all clients of a polymorphic object may be able to observe
its state to the degee as other clients, but that is not to say that
the object ever has more than a single state.

Quote:
Such an inference is mandatory under the current standard.
Am I right or wrong? Is this suggestion ontologically acceptable?

It sounds as if the goal is for the object to hold multiple values -
the constness of each could then be individually adjustable. If that is
the goal, then inheritance is not the right pattern. Instead the object
should use composition - instead of inheriting from IC, CC would have
an IC data member. in that way the constness of the CC object and the
constness of the CC object could be maintained in a more autonomous
manner.

Greg


---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Back to top
manphiz
Guest





PostPosted: Fri Oct 06, 2006 7:33 pm    Post subject: Re: overriding constant member functions Reply with quote

Quote:
In the following code, CC remains an abstract base class because
IC::foo(void) const remains unimplemented:
class IC { virtual void foo() const = 0; }; class CC { int m_x; void foo()
{ this->m_x = 0; }};
In order for CC::foo to override IC::foo, it must be declared as void foo()
const.
However, we cannot do that because this->m_x would be inferred constant.

Declaring this->m_x as mutable is one of the choices, in case that you
have to modify it in a const member function.

---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Back to top
Kristof Zelechovski
Guest





PostPosted: Sat Oct 07, 2006 4:23 pm    Post subject: Re: overriding constant member functions Reply with quote

Uzytkownik "Greg Herlihy" <greghe (AT) pacbell (DOT) net> napisal w wiadomosci
news:1160147636.738944.213430 (AT) c28g2000cwb (DOT) googlegroups.com...
Quote:


On Oct 5, 1:01 pm, giecr...@stegny.2a.pl ("Køi¹tof ®elechovski")
wrote:
In the following code, CC remains an abstract base class because
IC::foo(void) const remains unimplemented:
class IC { virtual void foo() const = 0; }; class CC { int m_x; void
foo()
{ this->m_x = 0; }};
In order for CC::foo to override IC::foo, it must be declared as void
foo()
const.

I think a better approach for implementing CC::foo() const would be to
write a const method for it - rather then rename one of CC's non-const
methods() in an attempt to pass it off as CC::foo() const. Frankly, it
is hard to see how CC::foo()'s current implementation could be
considered at all const.

However, we cannot do that because this->m_x would be inferred constant.

A method's const qualifier guarantees that calling the method will not
change the object's "value" or state. Now assigning zero to one of the
object's data members certainly appears like a change is being made to
the object's state. Presumably, the value of m_x means something to the
implementation of CC and that a change to its value would be detectable
by the client. If that is the case, then foo() is neither const nor
does it override CI's abstract foo() const method. The programmer needs
to use a different function.

I do not find this extension of constance justified.

But whoever designed CI's interface must feel otherwise. The foo method
would not be declared const unless the designer thought it is
reasonable to require that every derived class of CI, implement foo()
in a const way. Since we have no way of knowing what foo() is supposed
to do or what the data member m_x represents, we have no way of
evaluating whether this requirement seems at all reasonable or not. If
the const requirement is not reasonable than IC should declare the
method as non-const - it's not necessary to change the language to fix
that kind of problem.


I think a feeling is too vague a criterion to decide whether a method of the
interface should be constant or not.
The client code is generally free to provide implementations for the
vendor's interfaces
but it is not allowed to change the interfaces so it is already too late
when the client recognizes
that he does not feel good about a constant implementation
(every method can be made constant by using a constant pointer to the
implementation
but it is a dirty trick and the client need not like being forced to use
it).

Quote:
If CC::foo overrides IC::foo,
it must treat this as a pointer to a constant object of class IC, in that
no
member of class IC may be modified;
on the other hand, it is unreasonable to prohibit it from modifying
noninherited members of class CC.

Any change to any of the object's members is potentially a change to
the object's value - and therefore requires a non-const object. It's up
to the programmer, and not the language, to decide which members
contribute to the object's value and which do not. And it's far better
for the language to assume that all members are significant instead of
just some of them. In fact by what means would a programmer under these
new rules recreate the current behavior in which all members are
treated alike when evaluating the constness of an operation?


That rule would be observed unless the method is overriding.
If you want full constance of the actual object,
wrap the code in an original constant method and call the original method
from the overriding method.

Quote:
Generally speaking,
if a function takes a reference to a constant object,
it should be expected
that the function does not modify the members of the object that belong
to
its _declared_ type;

Declared where? And what members of an object would a function be
modifying if not the members of the object's declared type? What other
members would there be?


Declared in the declaration of the function.
E.g. if a function foo takes a reference to a constant object of base type,
the members of the derived type as declared in the base type
are guaranteed not to change via the reference
(remember that the object referred to by a reference to a constant object
need not be constant itself
- you cannot assume that the observable state of an object does not change
just because you refer to it as to a constant object).

Quote:
Such an inference is mandatory under the current standard.
Am I right or wrong? Is this suggestion ontologically acceptable?

It sounds as if the goal is for the object to hold multiple values -
the constness of each could then be individually adjustable. If that is
the goal, then inheritance is not the right pattern. Instead the object
should use composition - instead of inheriting from IC, CC would have
an IC data member. in that way the constness of the CC object and the
constness of the CC object could be maintained in a more autonomous
manner.


You cannot use composition in order to implement an interface, for two
reasons:
the interface is an abstract base class and you must use an implementation
to embed it,
which is just what you are trying to do,
and you cannot call the methods of the interface from client code unless you
inherit from it,
which would make such an "implementation" invisible for the server code.

Chris


---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Back to top
James Kanze
Guest





PostPosted: Sun Oct 08, 2006 7:14 pm    Post subject: Re: overriding constant member functions Reply with quote

"Kristof Zelechovski" wrote:
Quote:
Uzytkownik "Greg Herlihy" <greghe (AT) pacbell (DOT) net> napisal w wiadomosci
news:1160147636.738944.213430 (AT) c28g2000cwb (DOT) googlegroups.com...

[...]
Quote:
However, we cannot do that because this->m_x would be
inferred constant.

A method's const qualifier guarantees that calling the
method will not change the object's "value" or state. Now
assigning zero to one of the object's data members certainly
appears like a change is being made to the object's state.
Presumably, the value of m_x means something to the
implementation of CC and that a change to its value would be
detectable by the client. If that is the case, then foo() is
neither const nor does it override CI's abstract foo() const
method. The programmer needs to use a different function.

I do not find this extension of constance justified.

But whoever designed CI's interface must feel otherwise. The foo method
would not be declared const unless the designer thought it is
reasonable to require that every derived class of CI, implement foo()
in a const way. Since we have no way of knowing what foo() is supposed
to do or what the data member m_x represents, we have no way of
evaluating whether this requirement seems at all reasonable or not. If
the const requirement is not reasonable than IC should declare the
method as non-const - it's not necessary to change the language to fix
that kind of problem.

I think a feeling is too vague a criterion to decide whether a
method of the interface should be constant or not.

I don't think that Greg was using the work "feeling" to
expression a vague sentiment. In this case, it has a much
stronger meaning. Basically, the author of the base class
decided that the contract for this function would be that it has
no effects on the logical value of the object. And it's up to
the author of the base class to establish the contract.

Quote:
The client code is generally free to provide implementations
for the vendor's interfaces but it is not allowed to change
the interfaces so it is already too late when the client
recognizes that he does not feel good about a constant
implementation (every method can be made constant by using a
constant pointer to the implementation but it is a dirty trick
and the client need not like being forced to use it).

On the other hand, there is likely to be code that depends on
the fact that calling the function does not modify the
observable state. Regardless of the const (i.e. in languages
which don't support const), if the contract says you don't
modify the observable state, you'd better not modify the
observable state if you want the code to work.

It just happens that in C++, we can make this part of the
contract part of the type system.

--
James

---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ language, library and standards All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.