Path: csiph.com!news.mixmin.net!eternal-september.org!reader01.eternal-september.org!.POSTED!not-for-mail
From: Tim Rentsch
Newsgroups: comp.lang.c++
Subject: Re: Virtual functions: To const, or not to const?
Date: Mon, 10 Oct 2022 09:43:26 -0700
Organization: A noiseless patient Spider
Lines: 58
Message-ID: <86zge3hbo1.fsf@linuxsc.com>
References:
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Injection-Info: reader01.eternal-september.org; posting-host="3c67835d7e1bd6fce16ecef79276b22a"; logging-data="900710"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX19KCxR1E2MsmdEFGzD/ZpiG1k3g5jV1AJg="
User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.4 (gnu/linux)
Cancel-Lock: sha1:PinctmGFptKe5WTQMNw3mBkH3Tc= sha1:499Bn0/wzUpyRkp9IxU7Vl1gmZQ=
Xref: csiph.com comp.lang.c++:86859
Paavo Helde writes:
> 10.10.2022 09:20 Juha Nieminen kirjutas:
>
>> David Brown wrote:
>>
>>> Shouldn't it be a matter of deciding whether the function logically
>>> changes the object or not? If it clearly changes the object, it must be
>>> non-const. But if it leaves the object with the same publicly visible
>>> state, make it const. Any later bits that might need changing should be
>>> mutable.
>>>
>>> A virtual function is an interface, not implementation detail. It
>>> doesn't make sense to me to have a virtual function that is logically
>>> const in a base class, but logically non-const in a derived class.
>>
>> There are situations where the base class function is *so* abstract that
>> it doesn't even express if the derived class implementations should be
>> mutable or const. Some derived classes might want to implement as a
>> non-const function, other derived classes as a const function (so that
>> it can be called with const objects/references).
>
> If that's really so, then it looks like you have got two different
> class hierarchies or at least two interfaces, not one.
Right. I was wondering how long it would be before someone would
reach this conclusion.
Here is an outline for a scheme that supplies each of the four
logically distinct possibilities:
struct super_neither {
protected:
unsigned u_;
public:
super_neither() : u_(0) {}
virtual ~super_neither();
};
struct super_mutable_only : public virtual super_neither {
virtual unsigned u() { return ++u_; }
};
struct super_nonmutable_only : public virtual super_neither {
virtual unsigned u() const { return 1+u_; }
};
struct super_both : public super_mutable_only, super_nonmutable_only {
virtual unsigned u() { return super_mutable_only::u(); }
virtual unsigned u() const { return super_nonmutable_only::u(); }
};
Different subclasses should choose whichever of the four given
superclasses that is most appropriate to their individual needs.
Disclaimer: code intended only to illustrate the approach; some
details may need changing, depending on particular circumstances.