Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c++ > #86825 > unrolled thread
| Started by | Juha Nieminen <nospam@thanks.invalid> |
|---|---|
| First post | 2022-10-07 09:47 +0000 |
| Last post | 2022-10-08 21:42 +0200 |
| Articles | 20 — 12 participants |
Back to article view | Back to comp.lang.c++
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
| From | Juha Nieminen <nospam@thanks.invalid> |
|---|---|
| Date | 2022-10-07 09:47 +0000 |
| Subject | Virtual 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]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2022-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]
| From | Juha Nieminen <nospam@thanks.invalid> |
|---|---|
| Date | 2022-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]
| From | Richard Damon <Richard@Damon-Family.org> |
|---|---|
| Date | 2022-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]
| From | Juha Nieminen <nospam@thanks.invalid> |
|---|---|
| Date | 2022-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]
| From | Richard Damon <Richard@Damon-Family.org> |
|---|---|
| Date | 2022-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]
| From | Paavo Helde <eesnimi@osa.pri.ee> |
|---|---|
| Date | 2022-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]
| From | Tim Rentsch <tr.17687@z991.linuxsc.com> |
|---|---|
| Date | 2022-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]
| From | Tim Rentsch <tr.17687@z991.linuxsc.com> |
|---|---|
| Date | 2022-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]
| From | Paavo Helde <eesnimi@osa.pri.ee> |
|---|---|
| Date | 2022-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]
| From | Richard Damon <Richard@Damon-Family.org> |
|---|---|
| Date | 2022-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]
| From | Öö Tiib <ootiib@hot.ee> |
|---|---|
| Date | 2022-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]
| From | "Alf P. Steinbach" <alf.p.steinbach@gmail.com> |
|---|---|
| Date | 2022-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]
| From | Bonita Montero <Bonita.Montero@gmail.com> |
|---|---|
| Date | 2022-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]
| From | Michael S <already5chosen@yahoo.com> |
|---|---|
| Date | 2022-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]
| From | Bonita Montero <Bonita.Montero@gmail.com> |
|---|---|
| Date | 2022-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]
| From | Mr Flibble <flibble@reddwarf.jmc.corp> |
|---|---|
| Date | 2022-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]
| From | Bonita Montero <Bonita.Montero@gmail.com> |
|---|---|
| Date | 2022-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]
| From | Muttley@dastardlyhq.com |
|---|---|
| Date | 2022-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]
| From | Manfred <noname@add.invalid> |
|---|---|
| Date | 2022-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