D - Multiple inheritance
- Dave Emberton (16/16) Jan 17 2002 Sorry if this has come up before..
- Pavel Minayev (22/33) Jan 17 2002 down
- Dave Emberton (12/22) Jan 17 2002 multiple
- Walter (5/10) Jan 17 2002 The "is multiple inheritance useful or just a bug" discussion goes back ...
- Dave Emberton (14/17) Jan 18 2002 If multiple inheritance truly isn't useful, then why have it at all? You...
- Russ Lewis (119/130) Jan 18 2002 According to OOP theory, multiple inheritance is a good idea. But it's ...
- J. Daniel Smith (49/180) Jan 18 2002 Yes. As I understand Walter's reasoning, he's omitting "full" multiple
- Walter (10/23) Jan 18 2002 got
- Juan Carlos Arevalo Baeza (34/59) Jan 18 2002 about
- Dave Emberton (41/82) Jan 18 2002 very
- Russ Lewis (25/43) Jan 18 2002 But that's exactly the point - none (or very few) of the compilers ever ...
- la7y6nvo shamko.com (20/29) Jan 24 2002 I think there is general agreement that multiple inheritance is (which
- Russell Borogove (21/39) Jan 24 2002 That seems like a bogus argument. If a library designer feels
Sorry if this has come up before.. This was all looking good to me until I read one thing: "D classes support the single inheritance paradigm, extended by adding support for interfaces. " For me this relegates D from the level of an improved and tidied up C++ down to the level of Java - i.e. useful for some purposes but without the real power and flexibility of C++. I'm sure some would disagree, but why was this feature missed out of D? I can only assume that the designer(s) of D doesn't use multiple inheritance themselves so decided it was superfluous. As RTTI is part of the language (I assume this means all casts are effectively dynamic_cast's), then I can't see a good reason for this other than wanting to use the super() keyword to call the base class rather than specifying the base class by name. I've also just been reading about the lack of template support, which again is a bit sad. Dave
Jan 17 2002
"Dave Emberton" <demberton-nospam nospam.digitalworkshop.com> wrote in message news:a2698l$31fo$1 digitaldaemon.com...For me this relegates D from the level of an improved and tidied up C++downto the level of Java - i.e. useful for some purposes but without the real power and flexibility of C++. I'm sure some would disagree, but why wasthis And without bloat and complexity of C++, I must add... In most cases, interfaces are just enough where you'd use C++-style multiple inheritance. Some rare cases when it is really useful simply don't worth it, IMO. Remember the phrase from the D reference? "If a language can capture 90% of the power of C++ with 10% of its complexity, I argue that is a worthwhile tradeoff." I agree wholeheartedly.feature missed out of D? I can only assume that the designer(s) of Ddoesn'tuse multiple inheritance themselves so decided it was superfluous. As RTTI is part of the language (I assume this means all casts are effectively dynamic_cast's), then I can't see a good reason for this other thanwanting Yes, all object casts are safe - they return null if type doesn't match (see cast.d - some info about internal structure of D classes can be borrowed from there).to use the super() keyword to call the base class rather than specifyingthebase class by name.You can do the latter as well, by the way =) "super" is simply a shorter form.I've also just been reading about the lack of template support, whichagainis a bit sad.Walter says templates will be in sooner or later. The compiler is still in too early stage to judge, anyhow.
Jan 17 2002
"Pavel Minayev" <evilone omen.ru> wrote in message news:a26fj0$3oi$1 digitaldaemon.com..."Dave Emberton" <demberton-nospam nospam.digitalworkshop.com> wrote in message news:a2698l$31fo$1 digitaldaemon.com...And without bloat and complexity of C++, I must add... In most cases, interfaces are just enough where you'd use C++-stylemultipleinheritance. Some rare cases when it is really useful simply don't worth it, IMO.Having spent the last 5 years working on a large project that uses multiple inheritance extensively I have to disagree ;-) But in this case there was a particular reason for it, it's not always that useful I agree.Remember the phrase from the D reference? "If a language can capture 90% of the power of C++ with 10% of its complexity, I argue that is a worthwhile tradeoff." I agree wholeheartedly.Okay - but I don't think that the lack of multiple inheritance makes the language any less complex, because if you don't need it you just don't use it. The only place multiple inheritence causes major problems is when you have diamond inheritence with virtual base classes, and I'd be happy for that to be left out. Dave
Jan 17 2002
"Dave Emberton" <demberton-nospam nospam.digitalworkshop.com> wrote in message news:a26h9g$5f5$1 digitaldaemon.com...Okay - but I don't think that the lack of multiple inheritance makes the language any less complex, because if you don't need it you just don't use it. The only place multiple inheritence causes major problems is when you have diamond inheritence with virtual base classes, and I'd be happy for that to be left out.The "is multiple inheritance useful or just a bug" discussion goes back at least 10 years to when it was first proposed to be added to C++. The arguments have surged to and fro ever since <g>.
Jan 17 2002
"Walter" <walter digitalmars.com> wrote in message news:a27dpc$pee$1 digitaldaemon.com...The "is multiple inheritance useful or just a bug" discussion goes back at least 10 years to when it was first proposed to be added to C++. The arguments have surged to and fro ever since <g>.If multiple inheritance truly isn't useful, then why have it at all? You've taken the Java approach by being able to inherit from one class and several interfaces, which is kind of "multiple inheritance lite". I think most people will see how being able to inherit from multiple interfaces is useful, so why does anyone think that being able to inherit from multiple implementiations (or partial implementations) of those interfaces is not also useful? And as I said, if you don't want to use multiple inheritance then the fact that the language can do it won't get in your way. It just seems completely unnecessary to me. Surely one of the ways to improve on C++ is to make it more object oriented, not less. Dave
Jan 18 2002
Dave Emberton wrote:If multiple inheritance truly isn't useful, then why have it at all? You've taken the Java approach by being able to inherit from one class and several interfaces, which is kind of "multiple inheritance lite". I think most people will see how being able to inherit from multiple interfaces is useful, so why does anyone think that being able to inherit from multiple implementiations (or partial implementations) of those interfaces is not also useful? And as I said, if you don't want to use multiple inheritance then the fact that the language can do it won't get in your way. It just seems completely unnecessary to me. Surely one of the ways to improve on C++ is to make it more object oriented, not less.According to OOP theory, multiple inheritance is a good idea. But it's very difficult to pull off practically in a compiled language. The heart of the matter (to me) is that if we leave out multiple inheritance, the compiler will be simpler, smaller, less likely to have bugs (because it's easier to debug) and will be available sooner. From a technical sense, let me describe at the difficulties of MI. The first thing to remember is that a class is more or less just a structure with some compiler support that makes member function calls easy. Look at the following classes: class Foo { int i,j; int GetI() { return i; } int GetJ() { return j; } } class FooChild : Foo { int GetJ() { return 0; } } Note that there is one non-virtual member function and one virtual member function. The declaration above is somewhat like this C declaration: struct Foo { int i,j; struct { int (*GetJ)(struct Foo*); } vtable; } int Foo_GetI(struct Foo *this) { return this->i; }; int Foo_GetJ(struct Foo *this) { return this->j; }; struct FooChild { Foo parent_Foo; } int FooChild_GetJ(struct Foo *this) { return 0; }; When you create a "Foo" object, the compiler initializes the "vtable.GetJ" variable to point to "Foo_GetJ". When you create a "FooChild" object, it initializes "parent_Foo.vtable.GetJ" to point to "FooChild_GetJ". The beauty of this setup is that the parent Foo object is right at the beginning of the FooChild; thus any pointer to FooChild can be cast to a pointer to Foo without ever modifying the pointer. And since the Foo object is included whole within the FooChild, then the Foo REALLY IS there...with no special code needed, no changes required in Foo. Now consider what happens when you add a class Bar and derive Baz from Foo and Bar: class Bar { int i; int GetI() { return i*3; }; } class Baz : Foo, Bar { } Now, how do you implement this in C???? This is the closest I can come, but it's really ugly: struct Bar { int i; } int GetI(struct Bar *this) { return this->i*3; } struct Baz { Foo parent_Foo; Bar parent_Bar; } Now what does the compiler do when you try to call Baz::GetI()??? Or access Baz::i??? The answers are ambiguous unless you define complex rules for the language. Also, you can't cast a pointer to Baz to a pointer to Bar without modifying the pointer variable. Things get even worse when you have "diamond inheritance," where the same base class is included twice through two different children: class Fred : Foo {}; class Wilma : Foo {}; class Pebbles : Fred, Wilma {}; If you include two copies of Foo (the one that's part of Fred and the one that's part of Wilma), then you can't say that "Pebbles ISA Foo"...you say that "Pebbles INCLUDESA Foo (two of them)." But if you include only one copy of Foo, then you have screwed up the code in either Fred or Wilma. This is where C++ ends up having virtual classes and such. ugh. The beauty of the Java/D alternative is that you avoid all these complexities. Interfaces can be modeled as structures that are just lists of virtual function pointers. class Barney { int i; int GetI() { return i; } } class Betty { int j; int GetJ(); } interface BettyInt { int GetJ(); } class Bambam : Barney,BettyInt { // inherits i and GetI from Barney Betty betty; int GetJ() { return betty->GetJ(); } } Now this has a very workable implementation: struct Barney { int i; } int Barney_GetI(struct Barney *this) { return this->i; } struct Betty { int j; } int Betty_GetJ(struct Betty *this) { return this->j; } struct BettyInt { int (*GetJ)(void*); } struct Bambam { Barney parent_Barney; Betty betty; } int Bambam_GetJ(struct Bambam *this) { return Betty_GetJ(this->betty); } When you cast a pointer to Bambam into a pointer to Betty, it just takes the GetJ that Bambam has and stores that in the BettyInt. The beauty here is that the one object you inherit doesn't have ANY implementation changes, and the interface is defined from the very beginning to be nothing but a huge vtable. This vastly simplifies the compiler. Now, I'm not arguing that multiple inheritance is structurally bad...but it is difficult to implement for relatively little gain. -- The Villagers are Online! villagersonline.com .[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ] .[ (a version.of(English).(precise.more)) is(possible) ] ?[ you want.to(help(develop(it))) ]
Jan 18 2002
Yes. As I understand Walter's reasoning, he's omitting "full" multiple inheritence for practical reasons, not philisophical ones. It's not about whether or not multiple inheritence is useful, it's about developing a language in which you stand a better chance of writing bug-free code and having a compiler which correctly implements that language. As can be seen from the C++ specification, getting all the details for complete multiple inheritence specified is hard enough; but then you've got to write a compiler which correctly implements all of that. Everything is much simplier with just multiple interface inheritence and combined with aggregation/delegation you can usually get the job done. Why add a feature that is really only absolutely required 10% of the time and then is very difficult to get right? If you really must have full multiple inheritence, then C++ is the right tool to use. Dan "Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message news:3C484184.758215B deming-os.org...Dave Emberton wrote:You'veIf multiple inheritance truly isn't useful, then why have it at all?severaltaken the Java approach by being able to inherit from one class andmultipleinterfaces, which is kind of "multiple inheritance lite". I think most people will see how being able to inherit from multiple interfaces is useful, so why does anyone think that being able to inherit fromfactimplementiations (or partial implementations) of those interfaces is not also useful? And as I said, if you don't want to use multiple inheritance then thecompletelythat the language can do it won't get in your way. It just seemsitunnecessary to me. Surely one of the ways to improve on C++ is to makeverymore object oriented, not less.According to OOP theory, multiple inheritance is a good idea. But it'sdifficult to pull off practically in a compiled language. The heart ofthematter (to me) is that if we leave out multiple inheritance, the compilerwillbe simpler, smaller, less likely to have bugs (because it's easier todebug) andwill be available sooner. From a technical sense, let me describe at the difficulties of MI. The first thing to remember is that a class is more or less just astructurewith some compiler support that makes member function calls easy. Look atthefollowing classes: class Foo { int i,j; int GetI() { return i; } int GetJ() { return j; } } class FooChild : Foo { int GetJ() { return 0; } } Note that there is one non-virtual member function and one virtual member function. The declaration above is somewhat like this C declaration: struct Foo { int i,j; struct { int (*GetJ)(struct Foo*); } vtable; } int Foo_GetI(struct Foo *this) { return this->i; }; int Foo_GetJ(struct Foo *this) { return this->j; }; struct FooChild { Foo parent_Foo; } int FooChild_GetJ(struct Foo *this) { return 0; }; When you create a "Foo" object, the compiler initializes the "vtable.GetJ" variable to point to "Foo_GetJ". When you create a "FooChild" object, it initializes "parent_Foo.vtable.GetJ" to point to "FooChild_GetJ". The beauty of this setup is that the parent Foo object is right at thebeginningof the FooChild; thus any pointer to FooChild can be cast to a pointer toFoowithout ever modifying the pointer. And since the Foo object is includedwholewithin the FooChild, then the Foo REALLY IS there...with no special codeneeded,no changes required in Foo. Now consider what happens when you add aclass Barand derive Baz from Foo and Bar: class Bar { int i; int GetI() { return i*3; }; } class Baz : Foo, Bar { } Now, how do you implement this in C???? This is the closest I can come,butit's really ugly: struct Bar { int i; } int GetI(struct Bar *this) { return this->i*3; } struct Baz { Foo parent_Foo; Bar parent_Bar; } Now what does the compiler do when you try to call Baz::GetI()??? OraccessBaz::i??? The answers are ambiguous unless you define complex rules forthelanguage. Also, you can't cast a pointer to Baz to a pointer to Bar withoutmodifying thepointer variable. Things get even worse when you have "diamondinheritance,"where the same base class is included twice through two differentchildren:class Fred : Foo {}; class Wilma : Foo {}; class Pebbles : Fred, Wilma {}; If you include two copies of Foo (the one that's part of Fred and the onethat'spart of Wilma), then you can't say that "Pebbles ISA Foo"...you say that "Pebbles INCLUDESA Foo (two of them)." But if you include only one copyof Foo,then you have screwed up the code in either Fred or Wilma. This is whereC++ends up having virtual classes and such. ugh. The beauty of the Java/D alternative is that you avoid all thesecomplexities.Interfaces can be modeled as structures that are just lists of virtualfunctionpointers. class Barney { int i; int GetI() { return i; } } class Betty { int j; int GetJ(); } interface BettyInt { int GetJ(); } class Bambam : Barney,BettyInt { // inherits i and GetI from Barney Betty betty; int GetJ() { return betty->GetJ(); } } Now this has a very workable implementation: struct Barney { int i; } int Barney_GetI(struct Barney *this) { return this->i; } struct Betty { int j; } int Betty_GetJ(struct Betty *this) { return this->j; } struct BettyInt { int (*GetJ)(void*); } struct Bambam { Barney parent_Barney; Betty betty; } int Bambam_GetJ(struct Bambam *this) { return Betty_GetJ(this->betty); } When you cast a pointer to Bambam into a pointer to Betty, it just takestheGetJ that Bambam has and stores that in the BettyInt. The beauty here isthatthe one object you inherit doesn't have ANY implementation changes, andtheinterface is defined from the very beginning to be nothing but a hugevtable.This vastly simplifies the compiler. Now, I'm not arguing that multiple inheritance is structurally bad...butit isdifficult to implement for relatively little gain. -- The Villagers are Online! villagersonline.com .[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ] .[ (a version.of(English).(precise.more)) is(possible) ] ?[ you want.to(help(develop(it))) ]
Jan 18 2002
"J. Daniel Smith" <j_daniel_smith deja.com> wrote in message news:a29hl2$ka6$1 digitaldaemon.com...Yes. As I understand Walter's reasoning, he's omitting "full" multiple inheritence for practical reasons, not philisophical ones. It's not about whether or not multiple inheritence is useful, it's about developing a language in which you stand a better chance of writing bug-free code and having a compiler which correctly implements that language. As can be seen from the C++ specification, getting all the details for complete multiple inheritence specified is hard enough; but then you'vegotto write a compiler which correctly implements all of that. Everything is much simplier with just multiple interface inheritence and combined with aggregation/delegation you can usually get the job done. Why add a feature that is really only absolutely required 10% of the time and then is very difficult to get right? If you really must have full multiple inheritence, then C++ is the right tool to use.That's essentially correct. MI is a major implementation effort, but adds only minor incremental functionality to the language. MI has been around for 10 years in C++, and 10 years of experience has not made a compelling case that it's really necessary. Single inheritance handles 90% of the cases, adding interfaces handles 90% of the rest. That leaves 1% <g>. Yes, I do understand that some folks really do like MI and require it for their own style of programming.
Jan 18 2002
"Walter" <walter digitalmars.com> wrote in message news:a2a0f1$2q5j$1 digitaldaemon.com..."J. Daniel Smith" <j_daniel_smith deja.com> wrote in message news:a29hl2$ka6$1 digitaldaemon.com...aboutYes. As I understand Walter's reasoning, he's omitting "full" multiple inheritence for practical reasons, not philisophical ones. It's notiswhether or not multiple inheritence is useful, it's about developing a language in which you stand a better chance of writing bug-free code and having a compiler which correctly implements that language. As can be seen from the C++ specification, getting all the details for complete multiple inheritence specified is hard enough; but then you'vegotto write a compiler which correctly implements all of that. Everythingtimemuch simplier with just multiple interface inheritence and combined with aggregation/delegation you can usually get the job done. Why add a feature that is really only absolutely required 10% of theforand then is very difficult to get right? If you really must have full multiple inheritence, then C++ is the right tool to use.That's essentially correct. MI is a major implementation effort, but adds only minor incremental functionality to the language. MI has been around10 years in C++, and 10 years of experience has not made a compelling case that it's really necessary. Single inheritance handles 90% of the cases, adding interfaces handles 90% of the rest. That leaves 1% <g>. Yes, I do understand that some folks really do like MI and require it for their own style of programming.The only thing I've really used MI for is mixins. And there are better ways to do them. For example: --- interface NamedObject { void name(int newname); int name(); } mixin MyMixin: NamedObject { char[] m_Name; void name(int newname) { m_Name = newname; } int name() { return m_Name; } } class MyClass { MyMixin; } --- Which the compiler re-arranges (macro-style) into: --- class MyClass: NamedObject { char[] m_Name; void name(int newname) { m_Name = newname; } int name() { return m_Name; } } --- That would be tremendously useful. It's very similar to the concept of "modules" in Ruby, only done at compile-time. Salutaciones, JCAB
Jan 18 2002
"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message news:3C484184.758215B deming-os.org...According to OOP theory, multiple inheritance is a good idea. But it'sverydifficult to pull off practically in a compiled language. The heart ofthematter (to me) is that if we leave out multiple inheritance, the compilerwillbe simpler, smaller, less likely to have bugs (because it's easier todebug) andwill be available sooner.Okay - that's what we call engineering, and there's nothing wrong with that. But it seems a shame to limit a language because it would require more effort to write the compiler. The problems you mention have already been solved by C++ compilers, so it's not exactly impossible. No doubt the compiler would also be simpler if we left out contracts and unit tests and other features of D ;-) <snip>The beauty of this setup is that the parent Foo object is right at thebeginningof the FooChild; thus any pointer to FooChild can be cast to a pointer toFoowithout ever modifying the pointer. And since the Foo object is includedwholewithin the FooChild, then the Foo REALLY IS there...with no special codeneeded,no changes required in Foo. Now consider what happens when you add aclass Barand derive Baz from Foo and Bar: class Bar { int i; int GetI() { return i*3; }; } class Baz : Foo, Bar { } Now, how do you implement this in C???? This is the closest I can come,butit's really ugly: struct Bar { int i; } int GetI(struct Bar *this) { return this->i*3; } struct Baz { Foo parent_Foo; Bar parent_Bar; } Now what does the compiler do when you try to call Baz::GetI()??? OraccessBaz::i??? The answers are ambiguous unless you define complex rules forthelanguage.If you mean that both Foo and Bar have GetI() then the same as C++ - causes a compiler error. I don't see how anyone would ever want it to try and work it out. If you mean that Foo doesn't have a GetI, then I guess what the compiler needs to do is something like: Bar* pBar=(Bar*)((char*)pBaz)+sizeof(Foo) Bar_GetI(pBar)Also, you can't cast a pointer to Baz to a pointer to Bar withoutmodifying thepointer variable.True, but as all casts are dynamic_casts in D anyway, then a cast is never quite as simple as just using the same pointer value. Whatever mechanism makes that work must be able to make the multiple inheritance case work too.Things get even worse when you have "diamond inheritance," where the same base class is included twice through two differentchildren: As I said, I'd be happy for the diamond inheritance to be left out as it really is a bad idea.Now, I'm not arguing that multiple inheritance is structurally bad...butit isdifficult to implement for relatively little gain.True - but is the goal here to create a better language, or is the goal here to create a simpler compiler? From my point of view it's a shame that it's been left out, but I accept that others may have a completely different opinion. Dave-- The Villagers are Online! villagersonline.com .[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ] .[ (a version.of(English).(precise.more)) is(possible) ] ?[ you want.to(help(develop(it))) ]
Jan 18 2002
Dave Emberton wrote:Okay - that's what we call engineering, and there's nothing wrong with that. But it seems a shame to limit a language because it would require more effort to write the compiler. The problems you mention have already been solved by C++ compilers, so it's not exactly impossible. No doubt the compiler would also be simpler if we left out contracts and unit tests and other features of D ;-)But that's exactly the point - none (or very few) of the compilers ever got it all right! Rather than have a good standard, C++ is a mixmash of partially incompatible compilers. In truth, to get portable, reliable code, you pretty much have to dump most of the cooler features.If you mean that both Foo and Bar have GetI() then the same as C++ - causes a compiler error. I don't see how anyone would ever want it to try and work it out.My memory is that actually it *is* possible. If both GetI's are declared as virtual functions, then it is legal. Or do you only have to declare one of them virtual? If so, which one? The point is, very few people know what the standard actually is enough to be able to use it.As I said, I'd be happy for the diamond inheritance to be left out as it really is a bad idea.Since *all* classes in D are derived from Object, then every instance of multiple inheritance has to deal with diamon inheritance. :(I'm just not convinced that MI gives you a better language. But I am convinced that having partially-conforming, partially incompatible compilers gives you a worse language. So it seems that MI and stuff like that would be risking almost certain downsides against very small upsides. Now, OTOH, I'm not against defining a separate standard of some sort that takes a language much like D (but uses MI) and translates it down to D. That might be workable, and could almost certainly be written in a portable script format like PERL or something. Maybe we can call it D++ :) -- The Villagers are Online! villagersonline.com .[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ] .[ (a version.of(English).(precise.more)) is(possible) ] ?[ you want.to(help(develop(it))) ]Now, I'm not arguing that multiple inheritance is structurally bad...butit isdifficult to implement for relatively little gain.True - but is the goal here to create a better language, or is the goal here to create a simpler compiler? From my point of view it's a shame that it's been left out, but I accept that others may have a completely different opinion.
Jan 18 2002
"Dave Emberton" <demberton-nospam nospam.digitalworkshop.com> writes:If multiple inheritance truly isn't useful, then why have it at all? You've taken the Java approach by being able to inherit from one class and several interfaces, which is kind of "multiple inheritance lite". I think most people will see how being able to inherit from multiple interfaces is useful, so why does anyone think that being able to inherit from multiple implementiations (or partial implementations) of those interfaces is not also useful?I think there is general agreement that multiple inheritance is (which is to say, can be) useful. The question is, does multiple inheritance add enough utility to make it worth the cost of extra complexity in the language? It's hard to make a compelling case for multiple inheritance; perhaps one will be made, but I'm not aware of any example having been put forth. And I know of no study that's been done that tries to measure the cost of having multiple inheritance in a language.And as I said, if you don't want to use multiple inheritance then the fact that the language can do it won't get in your way.This idea - that one can ignore language features one doesn't use - is an old one, going back at least to the 1960's, but unfortunately it isn't right. The problem is, if multiple inheritance is there, someone (in fact lots of someones) will use it. Unless you're in the position of not working with other programmers, not working on code that other people write, not using any third party software, and not using any standard libraries, you almost certainly *are* going to encounter code that uses multiple inheritance, and then you'll no longer be able to ignore its presence. So I think the idea that language features can be used by people who want them and ignored by people who don't just isn't convincing.
Jan 24 2002
la7y6nvo shamko.com wrote:"Dave Emberton" <demberton-nospam nospam.digitalworkshop.com> writes:That seems like a bogus argument. If a library designer feels that multiple inheritance is important, that library designer is going to work in a language that supports it. If you and your coworkers can't agree on an acceptable language subset, you have worse problems than having to learn the perils of multiple inheritance.[1] In the particular case of MI, it seems pretty easy to ignore it even if some library class you're using uses it. The library can do its little MI dance, you can singly inherit from those library classes. If the library doesn't work right it's someone else's problem to understand and fix. To say otherwise is to make a case against using any middleware or third-party code in general, which is a separate discussion entirely. -Russell B [1] In 1994, I had to rewrite a nice chunk of code because my project lead wasn't comfortable with C++, and believed, or claimed to believe, that merely using classes -- without any virtual functions -- had unacceptable performance overhead. The team agreed to avoid C++, my code was rewritten, and I eventually quit.And as I said, if you don't want to use multiple inheritance then the fact that the language can do it won't get in your way.This idea - that one can ignore language features one doesn't use - is an old one, going back at least to the 1960's, but unfortunately it isn't right. The problem is, if multiple inheritance is there, someone (in fact lots of someones) will use it. Unless you're in the position of not working with other programmers, not working on code that other people write, not using any third party software, and not using any standard libraries, you almost certainly *are* going to encounter code that uses multiple inheritance, and then you'll no longer be able to ignore its presence. So I think the idea that language features can be used by people who want them and ignored by people who don't just isn't convincing.
Jan 24 2002
"Russell Borogove" <kaleja estarcion.com> wrote in message news:3C50E255.6020301 estarcion.com...[1] In 1994, I had to rewrite a nice chunk of code because my project lead wasn't comfortable with C++, and believed, or claimed to believe, that merely using classes -- without any virtual functions -- had unacceptable performance overhead. The team agreed to avoid C++, my code was rewritten, and I eventually quit.The solution there is easy - just run your C++ code through Cfront! Voila! It's now in C! You've all seen my complaints about C++, but performance of the resulting code isn't one of them. I've been careful in the design of D to not define behavior that mandates inefficient code generation. I still write most code on a 200 Mhz Pentium. Why not upgrade to a 1.7Ghz machine? Because it keeps my attention focussed on writing fast executing code. The only time I really miss a faster machine is when running the test suites, which take hours.
Jan 24 2002
"Russell Borogove" <kaleja estarcion.com> wrote in message news:3C50E255.6020301 estarcion.com...la7y6nvo shamko.com wrote:exactly why the argument for implementing X because language features that can be ignored is flawed, a sound argument for not implementing X."Dave Emberton" <demberton-nospam nospam.digitalworkshop.com> writes:That seems like a bogus argument. If a library designer feels that multiple inheritance is important, that library designer is going to work in a language that supports it. If you and your coworkers can't agree on an acceptable language subset, you have worse problems than having to learn the perils of multiple inheritance.[1]And as I said, if you don't want to use multiple inheritance then the fact that the language can do it won't get in your way.This idea - that one can ignore language features one doesn't use - is an old one, going back at least to the 1960's, but unfortunately it isn't right. The problem is, if multiple inheritance is there, someone (in fact lots of someones) will use it. Unless you're in the position of not working with other programmers, not working on code that other people write, not using any third party software, and not using any standard libraries, you almost certainly *are* going to encounter code that uses multiple inheritance, and then you'll no longer be able to ignore its presence. So I think the idea that language features can be used by people who want them and ignored by people who don't just isn't convincing.In the particular case of MI, it seems pretty easy to ignore it even if some library class you're using uses it. The library can do its little MI dance, you can singly inherit from those library classes. If the library doesn't work right it's someone else's problem to understand and fix. To say otherwise is to make a case against using any middleware or third-party code in general, which is a separate discussion entirely.then problem with MI in C++ is you get two types of inheritance Single Inheritance of one of the classes and containment of the others class B {}; class D :public B {}; you can pass D as a B and then get it back to a D but class A {}; class B {}; class D :public A,B {}; you can pass D as A or B, but only the A can be cast back to D, in C++ MI is realy just SI with cheap syntax for containment and automatically generated overloaded cast/pointer operations. C++ has a real headache even with virtual inheritance because the this pointer can not change if it did you would lose access to parts of you object. so you have to fully populate your Vtable. virtual inheritance, is saying lets add a member to my class that pointer to the location of my superclass does not solve the over all problem that casting can change the reference/pointer. Java has interfaces, to give light weight MI, it only allows virtual functions becuase of the way it works, it could have been made to work for member too. you still have to look to find out where in your object you "interface" is some method of allowing disimilar object to have an identical interface is required but full blown MI has too many nasties under the surface. not only is it a headache for the compiler writer is can be IMHO more work for the designer if you have to work with libraries that use it, than working out a design that does not require it. Mike.
Jan 25 2002