Prev: Lost in translation (with SPARK user rules)
Next: Sockets package in SPARK (Was: Lost in translation (with SPARK user rules))
From: Martin Krischik on 6 Jun 2010 08:04 Am 06.06.2010, 12:13 Uhr, schrieb Simon Wright <simon(a)pushface.org>: > "Martin Krischik" <krischik(a)users.sourceforge.net> writes: > >> One should just >> make a habit of defining classes like this: >> >> virtual Base >> { >> public: >> virtual ~Base () >> { >> … >> } >> } >> >> And suddenly all your virtual inheritance needs work flawlessly. > > I suppose there must be some cost to doing this? or the language > definition would require it to be always so. Yes indeed, you have virtual dispatch not only on the methods but on the instance variables as well. Sounds worth then it is. It means the internal structure of a child type changes from (Ada pseudo code): record Child_Type is Parent_Data : Parent_Type; end record to record Child_Type is Hidden_Parent_Data : Parent_Type; Parent_Data : constant access Parent_Type := Hidden_Parent_Data'Access; end record The compiler will ensure that Hidden_Parent_Data exist only once - but there may be any amount of Parent_Data which all point to the same Hidden_Parent_Data. And the funny part: The technology used to archive this is the very same you use to implement interfaces. Once you have the scaffolding for Interfaces in place you can have virtual base classes as well. Main problem with multiple inheritance was in C++ itself where default is “fast” not ”save”. For the Eiffel users it was never a problem because there virtual base classes are default. And I just see I made a mistake in my original post. It should have been: class Parent { public: virtual ~Parent () { … } } class Child virtual public Parent { … } but main problem stay: not enough C++ programmer have known about virtual inheritance and the diamond problem only pops up at Grand_Child level and lower (that means one has to plan ahead to avoid it). This in turn given multiple inheritance a bad name. But if you do it right it works just beautifully. The real lesson learned: “doing it right” must be default and “make it fast” must be an optional extra to be taught in very advanced level courses only. Martin -- Martin Krischik mailto://krischik(a)users.sourceforge.net https://sourceforge.net/users/krischik
From: Maciej Sobczak on 7 Jun 2010 04:13 On 6 Cze, 10:55, "Martin Krischik" <krisc...(a)users.sourceforge.net> wrote: > > Some people still think this is still a better trade-off over C++ styled > > multiple inheritance because of the dreaded "diamond" problem. > > which is easily solved by marking classes virtual. One should just make a > habit of defining classes like this: > > virtual Base > { > public: > virtual ~Base () > { > > } > } That will not work. Not just because it is invalid syntax, but because "virtualness" is a property of the relation between classes, not the property of any particular class. > And suddenly all your virtual inheritance needs work flawlessly. There are > just too many C++ programmers out there who do not know that. Not really, see my answer to your other post. -- Maciej Sobczak * http://www.inspirel.com YAMI4 - Messaging Solution for Distributed Systems http://www.inspirel.com/yami4
From: Maciej Sobczak on 7 Jun 2010 04:34 On 6 Cze, 14:04, "Martin Krischik" <krisc...(a)users.sourceforge.net> wrote: > > I suppose there must be some cost to doing this? or the language > > definition would require it to be always so. > > Yes indeed, you have virtual dispatch not only on the methods but on the > instance variables as well. No, such concept does not even make sense - instance variables themselves have no behavior and therefore cannot be "overriden". With virtual inheritance there is only one copy of the given instance variable within the whole object, so even the word "dispatch" cannot be applied there, as "dispatch" relates to "choice" and there is no choice. > Main problem with multiple inheritance was in C++ itself where default is > fast not save. No. Neither of these (non-virtual vs. virtual) is "fast" or "safe" in itself. Considering the performance aspect, the layout of variables within the object is determined *statically* (I have already explained that there is no "dispatch" involved), which means that there is no run-time cost in finding the given data item. All instance variables have some offset from the "beginning" of the object and that offset is computed statically, whether inheritance is virtual or not. There is no particular reason for any performance difference in data access, so it does not make any sense to say than one mode is "fast", while the other is not. Both are "fast" (it's C++, remember? ;-) ). Considering the safety aspect, the choice between non-virtual and virtual is design-dependent. Both make sense in some domain. For example, my mobile phone is able to send both text and multimedia messages. In both cases I might want to see the count of messages that were already sent and I want these counters to be *distinct*, not shared. This is a perfectly valid design (pseudo-code): class Countable; class TextMessager : public Countable; class MultimediaMessager : public Countable; class Phone : public TextMessager, public MultimediaMessager, ...; Now I have *separate* counters, both accessible with appropriate name paths (which makes perfect sense). Why is this a default? I don't know, but it's consistent with the fact that the whole object model is value-oriented, not interface-oriented. It's neither right nor wrong. (note: you might argue that the counter should be held by composition, not by extension - this is orthogonal to this discussion) > but main problem stay: not enough C++ programmer have known about virtual > inheritance Again, that knowledge would not necessarily help them, as the use of virtual inheritance is not automatically justified. > The real lesson learned: doing it right must be default Both ways are right. The default one is consistent with the overall object model. > and make it > fast must be an optional extra Both are fast. -- Maciej Sobczak * http://www.inspirel.com YAMI4 - Messaging Solution for Distributed Systems http://www.inspirel.com/yami4
From: Martin Krischik on 7 Jun 2010 04:35 Am 07.06.2010, 10:13 Uhr, schrieb Maciej Sobczak <see.my.homepage(a)gmail.com>: > That will not work. Not just because it is invalid syntax, but because > "virtualness" is a property of the relation between classes, not the > property of any particular class. Read my post below. Martin -- Martin Krischik mailto://krischik(a)users.sourceforge.net https://sourceforge.net/users/krischik
From: Martin Krischik on 7 Jun 2010 04:43
Am 07.06.2010, 10:13 Uhr, schrieb Maciej Sobczak <see.my.homepage(a)gmail.com>: >> And suddenly all your virtual inheritance needs work flawlessly. There >> are >> just too many C++ programmers out there who do not know that. > Not really, see my answer to your other post. So you think that all C++ programmers are perfect and know the ISO/IEC 14882:2003 from memory? Well the amount of C++ programming has reduced in recent years - maybe those who work in the business these days are of a better quality then those I knew. who knows. Martin -- Martin Krischik mailto://krischik(a)users.sourceforge.net https://sourceforge.net/users/krischik |