Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c++ > #86825 > unrolled thread

Virtual functions: To const, or not to const?

Started byJuha Nieminen <nospam@thanks.invalid>
First post2022-10-07 09:47 +0000
Last post2022-10-08 21:42 +0200
Articles 20 — 12 participants

Back to article view | Back to comp.lang.c++


Contents

  Virtual functions: To const, or not to const? Juha Nieminen <nospam@thanks.invalid> - 2022-10-07 09:47 +0000
    Re: Virtual functions: To const, or not to const? David Brown <david.brown@hesbynett.no> - 2022-10-07 12:50 +0200
      Re: Virtual functions: To const, or not to const? Juha Nieminen <nospam@thanks.invalid> - 2022-10-10 06:20 +0000
        Re: Virtual functions: To const, or not to const? Richard Damon <Richard@Damon-Family.org> - 2022-10-10 07:38 -0400
          Re: Virtual functions: To const, or not to const? Juha Nieminen <nospam@thanks.invalid> - 2022-10-10 12:08 +0000
            Re: Virtual functions: To const, or not to const? Richard Damon <Richard@Damon-Family.org> - 2022-10-10 20:47 -0400
        Re: Virtual functions: To const, or not to const? Paavo Helde <eesnimi@osa.pri.ee> - 2022-10-10 15:13 +0300
          Re: Virtual functions: To const, or not to const? Tim Rentsch <tr.17687@z991.linuxsc.com> - 2022-10-10 09:43 -0700
        Re: Virtual functions: To const, or not to const? Tim Rentsch <tr.17687@z991.linuxsc.com> - 2022-10-10 09:26 -0700
    Re: Virtual functions: To const, or not to const? Paavo Helde <eesnimi@osa.pri.ee> - 2022-10-07 14:00 +0300
    Re: Virtual functions: To const, or not to const? Richard Damon <Richard@Damon-Family.org> - 2022-10-07 07:29 -0400
    Re: Virtual functions: To const, or not to const? Öö Tiib <ootiib@hot.ee> - 2022-10-07 05:55 -0700
    Re: Virtual functions: To const, or not to const? "Alf P. Steinbach" <alf.p.steinbach@gmail.com> - 2022-10-08 14:56 +0200
    Re: Virtual functions: To const, or not to const? Bonita Montero <Bonita.Montero@gmail.com> - 2022-10-08 16:35 +0200
      Re: Virtual functions: To const, or not to const? Michael S <already5chosen@yahoo.com> - 2022-10-08 11:03 -0700
        Re: Virtual functions: To const, or not to const? Bonita Montero <Bonita.Montero@gmail.com> - 2022-10-08 20:36 +0200
        Re: Virtual functions: To const, or not to const? Mr Flibble <flibble@reddwarf.jmc.corp> - 2022-10-08 20:19 +0100
          Re: Virtual functions: To const, or not to const? Bonita Montero <Bonita.Montero@gmail.com> - 2022-10-10 17:58 +0200
        Re: Virtual functions: To const, or not to const? Muttley@dastardlyhq.com - 2022-10-09 09:19 +0000
    Re: Virtual functions: To const, or not to const? Manfred <noname@add.invalid> - 2022-10-08 21:42 +0200

#86825 — Virtual functions: To const, or not to const?

FromJuha Nieminen <nospam@thanks.invalid>
Date2022-10-07 09:47 +0000
SubjectVirtual functions: To const, or not to const?
Message-ID<thosit$6fp$1@gioia.aioe.org>
I have encountered this small dilemma several times. It's a question of
const correctness and proper OO design in C++.

Should a virtual function in a base class be const or not? This especially
in cases where it's very possible that a derived implementation wants
to change its own state (and thus would want the function to not be
const).

The answer seems simple enough: Obviously it's better to not make it
const, to allow for this possibility.

Problem is, when it's not const, now it can't be called using a const
instance, or const reference or pointer to one. There may be situations
where the only thing you have is a const version of the object, and
there's no way around that.

(Ok, technically speaking you *can* call it, by using const_cast. But
that's a really ugly solution, bad design, and in some cases might
even potentially break something. (Const code might assume the object
doesn't change.))

"Well, in that case offer *both* versions of the virtual function in
the base class, duh! Problem solved!"

Except that sometimes, in some situations, there may not be any
reasonable way to implement a const version of a function, because
it *has to* change the object in order to function correctly.
Sometimes a const version just doesn't make any sense. (For example,
a const version of std::vector::push_back() wouldn't make much
sense. What would it be supposed to do? Nothing? That would make
it really odd design, and would have the potential to break
something.)

This isn't even a question of "const correctness". It's a question
of getting a compiler error if all you have is a const reference
(and no way around that) and the virtual function happens to be
non-const (even though the implementation doesn't actually change
anything).

[toc] | [next] | [standalone]


#86826

FromDavid Brown <david.brown@hesbynett.no>
Date2022-10-07 12:50 +0200
Message-ID<thp091$3lkbh$1@dont-email.me>
In reply to#86825
On 07/10/2022 11:47, Juha Nieminen wrote:
> I have encountered this small dilemma several times. It's a question of
> const correctness and proper OO design in C++.
> 
> Should a virtual function in a base class be const or not? This especially
> in cases where it's very possible that a derived implementation wants
> to change its own state (and thus would want the function to not be
> const).
> 
> The answer seems simple enough: Obviously it's better to not make it
> const, to allow for this possibility.
> 
> Problem is, when it's not const, now it can't be called using a const
> instance, or const reference or pointer to one. There may be situations
> where the only thing you have is a const version of the object, and
> there's no way around that.
> 

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.

[toc] | [prev] | [next] | [standalone]


#86849

FromJuha Nieminen <nospam@thanks.invalid>
Date2022-10-10 06:20 +0000
Message-ID<ti0djb$1ghm$1@gioia.aioe.org>
In reply to#86826
David Brown <david.brown@hesbynett.no> 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).

There's really no way to allow for this in the base class. Making the
base class function const (and expecting the derived class to use
const cast to eg. call other of its own non-const functions) seems
a bit wrong. On the other hand, making it non-const now makes calling
the function with a const object harder. Declaring both a non-const
and const versions of the function may burden the derived class with
having to implement a const version that it can't logically implement.

All possible solutions have something wrong about them.

[toc] | [prev] | [next] | [standalone]


#86852

FromRichard Damon <Richard@Damon-Family.org>
Date2022-10-10 07:38 -0400
Message-ID<ZuT0L.60523$kEr7.55692@fx44.iad>
In reply to#86849
On 10/10/22 2:20 AM, Juha Nieminen wrote:
> David Brown <david.brown@hesbynett.no> 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).
> 
> There's really no way to allow for this in the base class. Making the
> base class function const (and expecting the derived class to use
> const cast to eg. call other of its own non-const functions) seems
> a bit wrong. On the other hand, making it non-const now makes calling
> the function with a const object harder. Declaring both a non-const
> and const versions of the function may burden the derived class with
> having to implement a const version that it can't logically implement.
> 
> All possible solutions have something wrong about them.

If the definition of what the function can do is that loose, then it 
isn't defined well enough to be an "interface".

If in some cases it must be able to be performed on a const object 
becuase it is defined to not change the object, but for other sub-types 
it can't be used on const objectes because it does change the object, 
then the operation isn't the "same" for all cases, and so you can't 
define the generic interface.

Given an object which you only know is of an object defined from 
something of that base, you don't know if you can use that operation on 
it. Thus, it can't be an actual interface.

It may be that all of them can use the non-const version, and specific 
sub-types can add (as an overload) a const version.

[toc] | [prev] | [next] | [standalone]


#86853

FromJuha Nieminen <nospam@thanks.invalid>
Date2022-10-10 12:08 +0000
Message-ID<ti11v2$1hq8$1@gioia.aioe.org>
In reply to#86852
Richard Damon <Richard@damon-family.org> wrote:
> If the definition of what the function can do is that loose, then it 
> isn't defined well enough to be an "interface".

That isn't very helpful if you are in this situation.

I suppose the answer is: "If you can't redesign the base class in such
a way that such ambiguity doesn't happen, then perhaps the best option
is to make it non-const and then in the derived class create a const
version that calls the non-const one using a const_cast. It might be
a bit ugly, but it's the best we got."

[toc] | [prev] | [next] | [standalone]


#86861

FromRichard Damon <Richard@Damon-Family.org>
Date2022-10-10 20:47 -0400
Message-ID<3331L.760268$BKL8.667135@fx15.iad>
In reply to#86853
On 10/10/22 8:08 AM, Juha Nieminen wrote:
> Richard Damon <Richard@damon-family.org> wrote:
>> If the definition of what the function can do is that loose, then it
>> isn't defined well enough to be an "interface".
> 
> That isn't very helpful if you are in this situation.
> 
> I suppose the answer is: "If you can't redesign the base class in such
> a way that such ambiguity doesn't happen, then perhaps the best option
> is to make it non-const and then in the derived class create a const
> version that calls the non-const one using a const_cast. It might be
> a bit ugly, but it's the best we got."

Which is sort of what I described, except I would probably define in the 
derived class the CONST version, and make the non-const version forward 
to it, since that is always well defined.

If the const version is called on an actual const object, and then it 
const-casts to the non-const version, and that ends up actually not 
being actually const, then you have invoked undefined behavior.


As I was pointing out, if you end up in this situation, your really need 
to evaluate why you got there, as something seems off.

[toc] | [prev] | [next] | [standalone]


#86854

FromPaavo Helde <eesnimi@osa.pri.ee>
Date2022-10-10 15:13 +0300
Message-ID<ti129g$qa0t$3@dont-email.me>
In reply to#86849
10.10.2022 09:20 Juha Nieminen kirjutas:
> David Brown <david.brown@hesbynett.no> 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.

Maybe the part(s) of the inheritance tree which you want to call over 
const references should be cut off and converted into a separate tree 
having a const interface.



[toc] | [prev] | [next] | [standalone]


#86859

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2022-10-10 09:43 -0700
Message-ID<86zge3hbo1.fsf@linuxsc.com>
In reply to#86854
Paavo Helde <eesnimi@osa.pri.ee> writes:

> 10.10.2022 09:20 Juha Nieminen kirjutas:
>
>> David Brown <david.brown@hesbynett.no> 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.

[toc] | [prev] | [next] | [standalone]


#86857

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2022-10-10 09:26 -0700
Message-ID<868rlniqzz.fsf@linuxsc.com>
In reply to#86849
Juha Nieminen <nospam@thanks.invalid> writes:

[...]

> All possible solutions have something wrong about them.

That's because what you're asking for is self-contradictory.  On
the one hand you want to be able to invoke the method on a const
reference.  On the other hand you want invoking the method on a
const reference to give a compile-time error.  Obviously the same
interface cannot do both, because either possibility necessarily
precludes the other.

[toc] | [prev] | [next] | [standalone]


#86827

FromPaavo Helde <eesnimi@osa.pri.ee>
Date2022-10-07 14:00 +0300
Message-ID<thp0rl$3lmsb$2@dont-email.me>
In reply to#86825
07.10.2022 12:47 Juha Nieminen kirjutas:
> I have encountered this small dilemma several times. It's a question of
> const correctness and proper OO design in C++.
> 
> Should a virtual function in a base class be const or not? This especially
> in cases where it's very possible that a derived implementation wants
> to change its own state (and thus would want the function to not be
> const).
> 


IMO, the 'const' should be applied logically. There is a virtual 
function which does something. Is this something that conceptually 
should not modify the object state? If yes, then make the virtual 
function const.

If a derived class overrides this function, it should conceptually still 
do something which does not modify the object. If it conceptually does, 
then it's possible you have bigger problems with the design, starting 
with the function name.

If the derived class modifies its state only technically, e.g. by 
caching something, we have means to express this in C++ cleanly - that's 
the 'mutable' keyword.

When following these rules, now if you have a const reference to the 
object and need to call a non-const virtual function on it, this means 
you want to call a function on a const object which might (again, 
conceptually) modify the object state. That's a design smell, and this 
is the exact reason why the language has the const qualifier in the 
first place - to catch such things at compile time so the design could 
be fixed.

In reality the things won't work out so nicely. In some cases the base 
class virtual interface is at so abstract level it is impossible to say 
if the functions might conceptually modify the object or not. According 
to the above guidelines these virtual functions should be non-const, 
which in turn means that this class cannot be really used via const 
references. In my code I have got several "non-const" classes which are 
basically always accessed only over non-const references. Yes, this 
looses the benefits of 'const', but at least it is honest about that and 
does not hide it behind a wall of const_cast-s.

Other scenario is e.g. with virtual functions which take callbacks or 
functors as arguments. Some callbacks might want to modify the object, 
some not. In that case one should provide two different virtual 
functions, one const and the other non-const.

If there is some override which does not make sense and which should not 
be called, then it's easy for me. I just put a debug assert failure and 
a runtime exception there.

hth
Paavo


[toc] | [prev] | [next] | [standalone]


#86828

FromRichard Damon <Richard@Damon-Family.org>
Date2022-10-07 07:29 -0400
Message-ID<24U%K.217670$IRd5.170462@fx10.iad>
In reply to#86825
On 10/7/22 5:47 AM, Juha Nieminen wrote:
> I have encountered this small dilemma several times. It's a question of
> const correctness and proper OO design in C++.
> 
> Should a virtual function in a base class be const or not? This especially
> in cases where it's very possible that a derived implementation wants
> to change its own state (and thus would want the function to not be
> const).
> 
> The answer seems simple enough: Obviously it's better to not make it
> const, to allow for this possibility.
> 
> Problem is, when it's not const, now it can't be called using a const
> instance, or const reference or pointer to one. There may be situations
> where the only thing you have is a const version of the object, and
> there's no way around that.
> 
> (Ok, technically speaking you *can* call it, by using const_cast. But
> that's a really ugly solution, bad design, and in some cases might
> even potentially break something. (Const code might assume the object
> doesn't change.))
> 
> "Well, in that case offer *both* versions of the virtual function in
> the base class, duh! Problem solved!"
> 
> Except that sometimes, in some situations, there may not be any
> reasonable way to implement a const version of a function, because
> it *has to* change the object in order to function correctly.
> Sometimes a const version just doesn't make any sense. (For example,
> a const version of std::vector::push_back() wouldn't make much
> sense. What would it be supposed to do? Nothing? That would make
> it really odd design, and would have the potential to break
> something.)
> 
> This isn't even a question of "const correctness". It's a question
> of getting a compiler error if all you have is a const reference
> (and no way around that) and the virtual function happens to be
> non-const (even though the implementation doesn't actually change
> anything).

The answer is that if the state isn't part of the visible state, make 
the state mutable, which means it CAN be changed in const objects and 
not giv problems.

If the state is part of the visible state, then you shouldn't really do 
that, as const functions shouldn't visible change the state, but it says 
the overriding doesn't really apply. A caller thining they are doing a 
constant operation on an object shouldn't find the object having changed.

You have a design issue is you have an operation that inherently might 
change the object but also needs to be implemented on const objects.

THAT is your problem.

[toc] | [prev] | [next] | [standalone]


#86829

FromÖö Tiib <ootiib@hot.ee>
Date2022-10-07 05:55 -0700
Message-ID<3c3069a0-cd27-44bd-9775-f82b29df2e97n@googlegroups.com>
In reply to#86825
On Friday, 7 October 2022 at 12:47:29 UTC+3, Juha Nieminen wrote:
> I have encountered this small dilemma several times. It's a question of 
> const correctness and proper OO design in C++. 
> 
> Should a virtual function in a base class be const or not? This especially 
> in cases where it's very possible that a derived implementation wants 
> to change its own state (and thus would want the function to not be 
> const). 

If it is not changing base class state only because the base class is kind
of dummy/refusing but otherwise it is logical to change state then of
course do not make method const. If it changes derived state only 
because of some internal efficiency or safety (caching, reporting, lazy
loading) but otherwise it is logical not to change state then make
member const but that state mutable. 

> The answer seems simple enough: Obviously it's better to not make it 
> const, to allow for this possibility. 
> 
> Problem is, when it's not const, now it can't be called using a const 
> instance, or const reference or pointer to one. There may be situations 
> where the only thing you have is a const version of the object, and 
> there's no way around that. 

If it logically mutates state of object then that is good that it can not
be called on const object. 

> (Ok, technically speaking you *can* call it, by using const_cast. But 
> that's a really ugly solution, bad design, and in some cases might 
> even potentially break something. (Const code might assume the object 
> doesn't change.)) 

Yes. That can break something.

> "Well, in that case offer *both* versions of the virtual function in 
> the base class, duh! Problem solved!" 
> 
> Except that sometimes, in some situations, there may not be any 
> reasonable way to implement a const version of a function, because 
> it *has to* change the object in order to function correctly. 

So you want the call to compile on const object despite it can't be
done on the const version? Then the const version can throw or refuse
in some other manner.

> Sometimes a const version just doesn't make any sense. (For example, 
> a const version of std::vector::push_back() wouldn't make much 
> sense. What would it be supposed to do? Nothing? That would make 
> it really odd design, and would have the potential to break 
> something.)

Then it is perfect that attempt to call push_back() on const object
gives compiling error. 

> This isn't even a question of "const correctness". It's a question 
> of getting a compiler error if all you have is a const reference 
> (and no way around that) and the virtual function happens to be 
> non-const (even though the implementation doesn't actually change 
> anything).

We can't have some kind of pre-decided silver bullet here. On
some cases we make virtual function non-const on other cases
const and on third cases provide both overloads. Logic is more or 
less same as without dynamic polymorphism. 
As always there can be some kind of grey area where it is not 
crisp clear what to do but such example needs to be looked at and
decided concretely and individually, general rules are hard to
establish.

[toc] | [prev] | [next] | [standalone]


#86834

From"Alf P. Steinbach" <alf.p.steinbach@gmail.com>
Date2022-10-08 14:56 +0200
Message-ID<thrs1f$6gav$1@dont-email.me>
In reply to#86825
On 7 Oct 2022 11:47, Juha Nieminen wrote:
> I have encountered this small dilemma several times. It's a question of
> const correctness and proper OO design in C++.
> 
> Should a virtual function in a base class be const or not? [snip]

Others have already answered this to my mind satisfactorily.

However, consider also the case of whether a non-virtual member function 
should be `const` or not.

One possible dilemma is proxy class like the one returned by 
`std::vector<bool>::operator[]`, where its assignment operator can and 
in my opinion should be `const` because it doesn't modify /that/ object,

     class Proxy
     {
     public:
         auto operator=( const bool value ) const -> Proxy;
     };

But the whole point of assignment is to modify an object, in this case 
the real `vector`. So I guess a case can be made that the assignment 
operator should not be `const`. E.g., the state that's observable via 
this proxy object, changes as a result of an assignment to it.

The reason that I think it should be `const` is that the `const` adds a 
constraint that can be useful for programmers: that /this/ object's 
internal non-`mutable` state doesn't change.

Nothing about "visible" state or that; for this case it's all about 
internal object state.

Then if one doesn't accept that as a universal criterion, and I DON'T, 
then the question is what is it that makes classes different in this 
respect?

I have no good answer.


- Alf

[toc] | [prev] | [next] | [standalone]


#86835

FromBonita Montero <Bonita.Montero@gmail.com>
Date2022-10-08 16:35 +0200
Message-ID<ths1rk$7039$2@dont-email.me>
In reply to#86825
There is no general answer or it depends on what you expect from
this interface. In individual cases, this question is then easy
to answer and therefore I do not know why it has to be discussed.

[toc] | [prev] | [next] | [standalone]


#86837

FromMichael S <already5chosen@yahoo.com>
Date2022-10-08 11:03 -0700
Message-ID<ad5ab9e6-6982-413e-82f6-dfcbc1b425a3n@googlegroups.com>
In reply to#86835
On Saturday, October 8, 2022 at 5:35:51 PM UTC+3, Bonita Montero wrote:
> There is no general answer or it depends on what you expect from 
> this interface. In individual cases, this question is then easy 
> to answer and therefore I do not know why it has to be discussed.

There is a general answer - don't use inheritance except as substitute
for interfaces, which typically means abstract classes with no data members.
All other forms of inheritance are known antipattern.
Use aggregation instead.

[toc] | [prev] | [next] | [standalone]


#86839

FromBonita Montero <Bonita.Montero@gmail.com>
Date2022-10-08 20:36 +0200
Message-ID<thsfuf$88m6$1@dont-email.me>
In reply to#86837
Am 08.10.2022 um 20:03 schrieb Michael S:
> On Saturday, October 8, 2022 at 5:35:51 PM UTC+3, Bonita Montero wrote:
>> There is no general answer or it depends on what you expect from
>> this interface. In individual cases, this question is then easy
>> to answer and therefore I do not know why it has to be discussed.
> 
> There is a general answer - don't use inheritance except as substitute
> for interfaces, which typically means abstract classes with no data members.
> All other forms of inheritance are known antipattern.
> Use aggregation instead.

Inheritance might be sometimes more difficult to handle.
But if you handle it correctly it's often less work than
with pure interfaces.

[toc] | [prev] | [next] | [standalone]


#86840

FromMr Flibble <flibble@reddwarf.jmc.corp>
Date2022-10-08 20:19 +0100
Message-ID<20221008201946.00004e88@reddwarf.jmc.corp>
In reply to#86837
On Sat, 8 Oct 2022 11:03:35 -0700 (PDT)
Michael S <already5chosen@yahoo.com> wrote:

> On Saturday, October 8, 2022 at 5:35:51 PM UTC+3, Bonita Montero
> wrote:
> > There is no general answer or it depends on what you expect from 
> > this interface. In individual cases, this question is then easy 
> > to answer and therefore I do not know why it has to be discussed.  
> 
> There is a general answer - don't use inheritance except as substitute
> for interfaces, which typically means abstract classes with no data
> members. All other forms of inheritance are known antipattern.
> Use aggregation instead.

Bullshit. Whilst in general composition is to be preferred over
inheritance there is nothing fundamentally wrong with deep inheritance
hierarchies if you have the slightest clue; it certainly is NOT an
anti-pattern: it is just another tool in the toolbox.

/Flibble

[toc] | [prev] | [next] | [standalone]


#86855

FromBonita Montero <Bonita.Montero@gmail.com>
Date2022-10-10 17:58 +0200
Message-ID<ti1fee$remf$1@dont-email.me>
In reply to#86840
Am 08.10.2022 um 21:19 schrieb Mr Flibble:
> On Sat, 8 Oct 2022 11:03:35 -0700 (PDT)
> Michael S <already5chosen@yahoo.com> wrote:
> 
>> On Saturday, October 8, 2022 at 5:35:51 PM UTC+3, Bonita Montero
>> wrote:
>>> There is no general answer or it depends on what you expect from
>>> this interface. In individual cases, this question is then easy
>>> to answer and therefore I do not know why it has to be discussed.
>>
>> There is a general answer - don't use inheritance except as substitute
>> for interfaces, which typically means abstract classes with no data
>> members. All other forms of inheritance are known antipattern.
>> Use aggregation instead.
> 
> Bullshit. Whilst in general composition is to be preferred over
> inheritance there is nothing fundamentally wrong with deep inheritance
> hierarchies ...

There's nothing wrong in a sense that there's usually no alternative.
But nevertheless these hierarchies might be hard to design.

[toc] | [prev] | [next] | [standalone]


#86843

FromMuttley@dastardlyhq.com
Date2022-10-09 09:19 +0000
Message-ID<thu3nu$fbl$1@gioia.aioe.org>
In reply to#86837
On Sat, 8 Oct 2022 11:03:35 -0700 (PDT)
Michael S <already5chosen@yahoo.com> wrote:
>On Saturday, October 8, 2022 at 5:35:51 PM UTC+3, Bonita Montero wrote:
>> There is no general answer or it depends on what you expect from 
>> this interface. In individual cases, this question is then easy 
>> to answer and therefore I do not know why it has to be discussed.
>
>There is a general answer - don't use inheritance except as substitute
>for interfaces, which typically means abstract classes with no data members.
>All other forms of inheritance are known antipattern.

What a load of nonsense. The java system of extending an interface is next to
useless compared to proper inheritence.

>Use aggregation instead.

I don't think you understand the different use cases of inheritence vs
aggregation.

[toc] | [prev] | [next] | [standalone]


#86841

FromManfred <noname@add.invalid>
Date2022-10-08 21:42 +0200
Message-ID<thsjs1$1d02$1@gioia.aioe.org>
In reply to#86825
On 10/7/2022 11:47 AM, Juha Nieminen wrote:
> I have encountered this small dilemma several times. It's a question of
> const correctness and proper OO design in C++.
> 
> Should a virtual function in a base class be const or not? This especially
> in cases where it's very possible that a derived implementation wants
> to change its own state (and thus would want the function to not be
> const).

As others have said, 'const'-ness is not really correlated with the 
function being virtual or not; rather, it is a design choice strictly 
coupled with the expected behavior (or contract) of the function.
In short, if it changes the (logical) state of the object, then it's 
just non-const; if it doesn't, and it is not meant to change it, then it 
may be (and probably is best, if you are convinced of your design) 
qualified as const.

I'll add that during a course on C++ design, more than two decades ago, 
the guy stressed that 'const is a very strong qualifier' in the C++ type 
system.
Emphasis on /strong/, meaning that the decision whether some member is 
or is not const should be considered thoroughly in C++ design, despite 
how tiny the change is in code.
If, later along the way, you find yourself in the need of changing that 
design choice, then I'd either make a new function or at least make an 
overload (which, in C++, works well given the 'strong' nature of the 
qualifier)

<snip>

> Except that sometimes, in some situations, there may not be any
> reasonable way to implement a const version of a function, because
> it *has to* change the object in order to function correctly.

I see here one of two things happening: either the 'state' of the object 
or the semantics of the function is not defined properly.
A third, rare IME, alternative is that you would have some data member 
that is not really part of the logical state of the object - that's the 
use for 'mutable'.

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.c++


csiph-web