C++ Weekly - Ep 263 - Virtual Inheritance: Probably Not What You Think It Is

Поділитися
Вставка
  • Опубліковано 7 вер 2024
  • ☟☟ Awesome T-Shirts! Sponsors! Books! ☟☟
    Upcoming Workshop: C++ Best Practices, NDC TechTown, Sept 9-10, 2024
    ► ndctechtown.co...
    Upcoming Workshop: Applied constexpr: The Power of Compile-Time Resources, C++ Under The Sea, October 10, 2024
    ► cppunderthesea...
    T-SHIRTS AVAILABLE!
    ► The best C++ T-Shirts anywhere! my-store-d16a2...
    WANT MORE JASON?
    ► My Training Classes: emptycrate.com/...
    ► Follow me on twitter: / lefticus
    SUPPORT THE CHANNEL
    ► Patreon: / lefticus
    ► Github Sponsors: github.com/spo...
    ► Paypal Donation: www.paypal.com...
    GET INVOLVED
    ► Video Idea List: github.com/lef...
    JASON'S BOOKS
    ► C++23 Best Practices
    Leanpub Ebook: leanpub.com/cp...
    ► C++ Best Practices
    Amazon Paperback: amzn.to/3wpAU3Z
    Leanpub Ebook: leanpub.com/cp...
    JASON'S PUZZLE BOOKS
    ► Object Lifetime Puzzlers Book 1
    Amazon Paperback: amzn.to/3g6Ervj
    Leanpub Ebook: leanpub.com/ob...
    ► Object Lifetime Puzzlers Book 2
    Amazon Paperback: amzn.to/3whdUDU
    Leanpub Ebook: leanpub.com/ob...
    ► Object Lifetime Puzzlers Book 3
    Leanpub Ebook: leanpub.com/ob...
    ► Copy and Reference Puzzlers Book 1
    Amazon Paperback: amzn.to/3g7ZVb9
    Leanpub Ebook: leanpub.com/co...
    ► Copy and Reference Puzzlers Book 2
    Amazon Paperback: amzn.to/3X1LOIx
    Leanpub Ebook: leanpub.com/co...
    ► Copy and Reference Puzzlers Book 3
    Leanpub Ebook: leanpub.com/co...
    ► OpCode Puzzlers Book 1
    Amazon Paperback: amzn.to/3KCNJg6
    Leanpub Ebook: leanpub.com/op...
    RECOMMENDED BOOKS
    ► Bjarne Stroustrup's A Tour of C++ (now with C++20/23!): amzn.to/3X4Wypr
    AWESOME PROJECTS
    ► The C++ Starter Project - Gets you started with Best Practices Quickly - github.com/cpp...
    ► C++ Best Practices Forkable Coding Standards - github.com/cpp...
    O'Reilly VIDEOS
    ► Inheritance and Polymorphism in C++ - www.oreilly.co...
    ► Learning C++ Best Practices - www.oreilly.co...

КОМЕНТАРІ • 112

  • @reverendragnarok
    @reverendragnarok 3 роки тому +29

    What he didn't touch on that has bitten me before is that virtual base class is default constructed before anything else, so the constructors of the derived have no control over them.

    • @cppweekly
      @cppweekly  3 роки тому +9

      I actually only recently learned about this myself, I do try to avoid designs like this, so the practical issues rarely come up for me.

    • @maxx666mayhem
      @maxx666mayhem 3 роки тому +1

      Yes this one is very interesting... Item 9 from Effective c++

    • @arturczajkowski4255
      @arturczajkowski4255 2 роки тому +2

      You are wrong. It is NOT default constructed (or put it differently, this isn't the requirements). It is constructed BEFORE its derived classes (but that is normal behavior).

    • @reverendragnarok
      @reverendragnarok 2 роки тому +1

      @@arturczajkowski4255 and what parameters are given to that constructor? The default ones.

    • @arturczajkowski4255
      @arturczajkowski4255 2 роки тому +4

      @@reverendragnarok No, not default ones. You can call any constructor with any params.

  • @perfectionbox
    @perfectionbox 3 роки тому +21

    tried that once. the more i coded it, the darker it got outside, the fuller the moon got, and the forest somehow grew closer while wolves started howling begging me to join them.

    • @larswadefalk6423
      @larswadefalk6423 3 роки тому +2

      Good way to describe it. It's a warning sign.

  • @atimholt
    @atimholt 3 роки тому +36

    The thing I love about C++ is its “attitude” of “there needs to at least be a way to do it”. Nothing should be actually impossible.

    • @WouterStudioHD
      @WouterStudioHD 3 роки тому +1

      Haha yes and 3 years later everything is in the standard

    • @ruroruro
      @ruroruro 3 роки тому +9

      Except having a stable ABI. Having a stable ABI is actually impossible.
      Or hygienic macros. Or reflection (for now at least). Or built-in garbage collection. Or readable compiler errors. Or a consistent std.

    • @lincolnsand5127
      @lincolnsand5127 3 роки тому +2

      @@ruroruro Tbh, gcc and clang have had provided pretty stable ABIs for a while now and even have options to avoid the std::string ABI break. The committee has also routinely rejected features that would cause compiler vendors to have to break ABI. So while C++ doesn't technically have a stable ABI, if you're on Unix using clang or gcc, your compiler vendor (and STL vendor) are providing a stable ABI based on Itanium.

    • @ruroruro
      @ruroruro 3 роки тому

      @@lincolnsand5127 well, I just recently had a bunch of problems with basic string ABI due to nvcc not supporting newer GCC versions.
      Also, ABI stability includes the binary representation of user-generated content, not only the std. So the lack of encapsulation for private members breaks the ABIs of user programs/libraries.

    • @yash1152
      @yash1152 Рік тому

      > _"needs to .. be a way to do it."_
      really? for the following situation too? I was facing problem at step 4 & 5:
      *Summary:*
      + initialising parent class's static member variable(s) in child class, and
      + using those initialised values to call a parent class static member function
      *Details:*
      1. I want to create static member variable (of type struct: sting, char, int or either individual variables), say "classSpecs" inside a "Base" class
      2. Now I want to create a static member function "putName()" to cout this "categorySpecs"
      3. Then i want to create hierarchial inheritance, i.e. two subclasses say "Child1", "Child2"
      4. Then I want some way to initiate the value of that struct "categorySpec" inside those subclasses.
      5. Then call "Base::putName()" from inside some (static?) member function of those subclasses by passing that initiated value.

  • @Omnifarious0
    @Omnifarious0 3 роки тому +26

    One important detail that you miss is that the virtual base must only be constructed once. And so then you have an interesting situation if both Intermediate2 and Intermediate3 call the constructor for Base. I believe that those constructor calls will be ignored, and Derived will have to call the constructor for the virtual Base. So if Base doesn't have a default constructor, Derived will have to call a constructor for a class that it isn't obviously derived from.
    I haven't tested this. This is just from what I recall of how this feature works. So, in other words, I might be wrong.

    • @vgarzareyna
      @vgarzareyna 3 роки тому +1

      It may be good to use C++ insights on that code

    • @ub880
      @ub880 3 роки тому

      That's correct. I had this problem some weeks ago.

    • @Omnifarious0
      @Omnifarious0 3 роки тому

      @@ub880 - Yeah, I had a comment here where I posted a little test I did with compiler explorer that showed that my memory was correct. Unfortunately, because it contained a link to compiler explorer, UA-cam ate it.

    • @stephenhowe4107
      @stephenhowe4107 2 роки тому

      Intermediate2 & Internediate3 will ignore the call to construct Base, that is if they are part of Derived.
      But here is the rub:
      Suppose you have some standalone objects Intermediate2 & Internediate3. Then they will call the Base constructor.
      How is this done? There is usually a hidden bool parameter which if true constructs Base and if false does not.
      So for Derived, that is true, Base is constructed, but then when Intermediate2 & Internediate3 are constructed, this passed as false.
      For standalone objects Intermediate2 & Internediate3, this hidden bool parameter constructs Base.
      Now I think about, there must be something similar for destructors, because the same issue arises.

  • @quamrana
    @quamrana 3 роки тому +8

    One super useful feature that virtual inheritance gives you is mixins. You can define lots of pure virtual methods in 'Base' and then implement different subsets of them in different 'Intermediate' classes. I think of it as 'Base' defining different features for the client, say feature A and feature B. Now, for each feature you *could* have different implementations in 'Intermediate' classes, but for each feature you pick one. So, feature B could be implemented in different ways, but for one particular 'Derived' class you pick just one of the many 'Intermediate' classes.

    • @ecosta
      @ecosta 3 роки тому +3

      When C++ does multiple inheritance, everybody goes “ewww”. When other languages do it, they call it “interfaces”, “mixin”, etc and it becomes the most important feature of that language.

  • @eca3101
    @eca3101 3 роки тому +33

    Me - programming in C++ for nearly a decade and never even heard about virtual inheritance till this video
    Thanks Jason, now I got some imposter syndrome haha - super helpful video though

    • @BigPapaMitchell
      @BigPapaMitchell 3 роки тому +12

      Diamond inheritance is uncommon design and usually a symptom of poor design.

    • @eca3101
      @eca3101 3 роки тому +7

      @@BigPapaMitchell thanks, so I’ll just assume that means I’m good at designing inheritance haha

    • @isura.m
      @isura.m 3 роки тому

      @@BigPapaMitchell Not a very experienced C++ programmer here. But I think Diamond inheritance happens often if all/many of your classes inherit from a base class that offers some functionality, for example, something similar to Java's 'Object'. In such a case, everything will be alright until there's a need to do multiple inheritance at some point.

    • @minciNashu
      @minciNashu 3 роки тому +1

      It's just one of those poorly asked interview questions.
      Instead of asking how to design against the problem, they ask how to workaround the problem with language syntax.

    • @AlfW
      @AlfW 3 роки тому +2

      @@BigPapaMitchellYes and no. I would say that Qt is well-designed. And in Qt, everything inherits from QObject.
      So you're in a case of diamond inheritance as soon as you do multiple inheritance. I guess that multiple inheritance itself is an antipattern, that's also why many languages don't support it.

  • @ecosta
    @ecosta 3 роки тому +2

    I’m sorry if I’m repeating someone’s comments, but this kind of trick is quite useful. C++ tuples heavily depends on multiple inheritance and we can do in C++ all sort of limited version other languages have, such as mixin, interfaces (even “modern” ones with “default” methods).

    • @yash1152
      @yash1152 Рік тому

      how mixin inheritance? also, how kotlin's extension functions?

  • @DamianReloaded
    @DamianReloaded 3 роки тому +7

    Avoiding multiple inheritance altogether improves code "reviewability" and maintainability. It is interesting how hard it is some times to keep things simple when you have many features. It's like an impulse of thinking "If I have this feature I must use it".

    • @DamianReloaded
      @DamianReloaded 3 роки тому +3

      ​@@mattmurphy7030 Generally speaking, older "more experienced" programmers tend to stick with what they know best and avoid implementing newer paradigms while younger more up to date graduates tend to miss the point entirely as to what kind of software design helps the most a Company to accomplish high maintainability and "refactorability". Microservices design kinda came into being to address exactly this problem in the industry.

    • @DamianReloaded
      @DamianReloaded 3 роки тому

      @Matt Murphy Brilliant. ^_^

    • @stephenhowe4107
      @stephenhowe4107 2 роки тому

      Not at all. Multiple inheritance is modelling situation. If you have a Mixin Class, your class might provide Services 1 and Services 2, both orthogonal to each other.
      Multiple inheritance allows you to model Mixin's. I certainly would not use multiple inheritance just for the sake of it.
      For that matter, iostreams in the standard - that uses multiple inheritance.

    • @DamianReloaded
      @DamianReloaded 2 роки тому

      @@stephenhowe4107 Avoiding means alternatives to MI are often preferable for various reason beyond your personal know-how. If you're an expert and you know from heart all the corner-cases of implementing multiple inheritance and you do it well and you alone are going to maintain it, then of course. It will always be an option regardless of what people generally agree are good practices.

  • @HiltonFernandes
    @HiltonFernandes 8 місяців тому

    Very interesting and well explained: C++ has a world inside it.

  • @essenceidentity
    @essenceidentity 3 роки тому +2

    Thanks for this one Jason !!! Always concise and to the point. It's such a blessing catching your *c++* tutorials always ;-)))))))))

  • @AllElectronicsGr
    @AllElectronicsGr 3 роки тому +4

    Amazing channel.

  • @BigBahss
    @BigBahss 3 роки тому +3

    This is great, I just discovered this a few days ago and was researching it myself, this did a really good job of explaining it.

  • @GuntranOnline
    @GuntranOnline 2 роки тому +1

    Brilliant explanation! Thanks.

  • @gauravchaudhary-nd8pt
    @gauravchaudhary-nd8pt Рік тому

    Excellent explanation !

  • @6754bettkitty
    @6754bettkitty 3 роки тому +4

    This video could have spared my coworker from explaining virtual inheritance many times to me.

  • @GuillaumePicquet
    @GuillaumePicquet 3 роки тому +3

    Diamond inheritance solve ! (never seen use case so far)

    • @-taz-
      @-taz- 3 роки тому

      It's fantastic for implementing the middle out algorithm.

  • @King0Mir
    @King0Mir 3 роки тому +14

    It's not quite true that it has nothing to do with virtual functions. Like virtual functions, this is adding an additional pointer to the class, here to keep track of the base. Was hoping you would go into that implementation more.

    • @6754bettkitty
      @6754bettkitty 3 роки тому +5

      Watch Arthur O'Dwyer's CppCon talk dynamic_cast from scratch. He goes into the details of virtual inheritance.

    • @minciNashu
      @minciNashu 3 роки тому +2

      The actual implementation is up to compiler.

    • @LEpigeon888
      @LEpigeon888 3 роки тому

      It doesn't add a new pointer, just add more entries in the vtable, no ? Not 100% sure.

    • @6754bettkitty
      @6754bettkitty 3 роки тому

      @@LEpigeon888 For virtual functions, it just adds more entries into the vtable, of course in the form of function pointers. I recommend watching the talk i mentioned above.

    • @LEpigeon888
      @LEpigeon888 3 роки тому

      @@6754bettkitty I've read quuxplusone.github.io/blog/2019/09/30/what-is-the-vtt/ , he said « Suppose Cat has a virtual base Animal. Then vtable for Cat holds not just function pointers to Cat’s virtual member functions, but also the offset of Cat’s virtual Animal subobject. ».
      So as far as i understand, everything is in the vtable, there is no additional pointer / data inside the class. At least for the Itanium ABI.

  • @Spongman
    @Spongman 3 роки тому +1

    oh man, you could do another whole video on pointers to member functions and fields in virtual inheritance hierarchies, their varying size, and how dispatch is implemented differently by different compilers.

  • @larswadefalk6423
    @larswadefalk6423 3 роки тому

    I have no problem with virtual inheritance and even multiple inheritance per se, it's usually very clear and a good way for abstracting the actual world. But if one run into the diamond inheritance situation, it's a sign for rethinking the structure of what you want to abstract and how to do it the most clear way. I have stumbled into it more than once and realized that I did things overly complex. If you start writing those extra virtuals on the inheritance, just be aware of what you are actually trying to achieve. You may than have a structural design problem.

  • @LucasGalfaso
    @LucasGalfaso 3 роки тому +1

    Virtual inheritance works somehow differently. In the example given with int1 and int2, then derived inherits from base directly. This is possible to check as if you make base constructor private and make int1/int2 friends of base, with virtual inheritance it will not compile as derived cannot have access to base private constructor.
    The only use I can think of for virtual inheritance is to make a class final, you use a template class with a private constructor that will friend the template class parameter and then inherit virtual from the template and pass the same class as template parameter (before c++11)

  • @PamirTea
    @PamirTea 3 роки тому

    Mindblowing

  • @mjKlaim
    @mjKlaim 3 роки тому +1

    I knew this for a long time, but I think it only make sense if you show how inheritance can be implemented in memory (with some graphics). Otherwise it looks totally random. Once you see how things can be put together in memory when working with inheritance, the feature becomes "logical" (though super niche)

    • @larswadefalk6423
      @larswadefalk6423 3 роки тому

      Actually this is not written in the standard for how the compiler implements the inheritance itself. It could be very well imagined yes, but there is nothing to rely on here. But you're right, it's at the same time interesting to get an idea of how virtual inheritance actually is laid out in memory. Not least for the indirections of pointers in assembly that it creates.This affects cache and in it's own way. The same that unrolled loops would do for cache hits and traversing lists etc., cache is an evergoing interesting problem if you think of optimisation.

    • @mjKlaim
      @mjKlaim 3 роки тому +1

      @@larswadefalk6423 Yes I know it's not specified, but explaining it implies having to explain that it's somewhere in memory, and that somewhere have an impact.

  • @stephenhowe4107
    @stephenhowe4107 2 роки тому

    I thought you were going to cover virtual operators.
    I have only had 1 situation where a virtual < operator was required
    If you have a base class that represents the States of America and you wish to have a std::set of them but the order could be Population, Area Size, Wealth etc, you might have a pure virtual < operator, and Derived classes where the < operator is overridden and provides ordering by Population, Area Size etc. Now you can do that. And call base class services.

  • @YSoreil
    @YSoreil 3 роки тому +1

    The magic glueing together of virtual inheritance in to all pointing to the same thing seems a bit weird. I don't think I have ever used or wanted to use this feature but now that I know it exists it will surely nag on my brain.

    • @Antibolit
      @Antibolit 3 роки тому +1

      One useful case I know of: imagine you have your own intrusive_ptr, and your classes are refcounted. And let's say you have an intrusive_ptr and an intrusive_ptr that both refer to the same object "Foo : public Producer, public Consumer".
      If you want to maintain the property that it can be owned as either of them, in languages like Java or C# it would just work (both `Producer foo` or `Consumer bar` can refer to and own the same implementation of both interfaces). In C++, it can be somewhat tricky.
      But with virtual inheritance, you can make this work, by making your interface-like abstract classes virtually inherit from some RefCountBase: "Producer : public virtual RefCountBase", "Consumer : public virtual RefCountBase". Now "Foo : public Producer, public Consumer" has only one internal copy of RefCountBase, so both intrusive pointers will be working with the same atomic refcount.

  • @OMGclueless
    @OMGclueless 3 роки тому

    You mentioned that virtual inheritance has nothing to do with virtual function calls. But it does have *something* to do with virtual function calls: When you use virtual inheritance, every call to a base class member function or access to a base class member variable is indirect and needs to use the vtable to get an offset. In this sense the performance costs are very similar to calling a virtual function.
    In some ways not quite as bad because there's no data dependency between the vtable load and the target of the `jmp` or `call` instruction which helps the compiler and CPU optimize the function call (it can even be inlined unlike a virtual call). In some ways worse because you now need the vtable to access member variables, not just to call functions. But long story short the use of the keyword "virtual" isn't an accident and actually a pretty good name given the similarities.

  • @e-sharp9366
    @e-sharp9366 3 роки тому +6

    Did someone say convoluted ?

  • @grahampitt8882
    @grahampitt8882 3 роки тому

    I was waiting for the epiphany here but it didnt come. It works exactly how I expect.
    The odd thing to me about virtual inheritance is that the intermediate class must make the choice of how the final composition will look. With virtual inheritance the indirection overhead of accessing the base may always be incurred even if the final hierarchy ends up including only one instance of the base class.
    The requirement to construct the virtual base in the most derived class is also an oddity, albeit an understandable one. The most unpleasant part of that for me is that sane looking code with an explicit construction in the intermediate class is not used, but instead it might be an implicit default construction in the most derived class and as of my last check that intermediate constructor call might be dead code if the class has a pure virtual call or no public constructors, etc. That to me is something that isnt particularly intuitive for the uninitiated.

  • @kalelalves
    @kalelalves 3 роки тому

    I wait for these episodes almost like I wait for my favorite tv series. haha

  • @shanehebert396
    @shanehebert396 3 роки тому

    A great example of why other languages disallow multiple object inheritance. :)

  • @TheMR-777
    @TheMR-777 2 роки тому +1

    Well, I guess I'm only one in the comments, who learned this concept in the early days of my C++ journey :)
    (It's been 2yrs roughly, since I learned it)

  • @jewulo
    @jewulo 3 роки тому

    So, should we just avoid inheritance and simply favor composition? Or is it virtual inheritance in every case? I was under the impression that inheritance was about marshaling, structuring, and organization of type hierarchies? Rather than the marshaling, structuring, and organization of values? In the all virtual case, it is about types. In the non-virtual or partially-virtual case, it seems to be about values?

  • @lincolnsand5127
    @lincolnsand5127 3 роки тому

    It is what I thought it was because I watched Arthur O'Dwyer's fantastic talk "dynamic_cast" from scratch a few months ago lol. Anyways, good video on the topic

  • @QuickNETTech
    @QuickNETTech 3 роки тому +15

    As I'm watching this the only thing coming to mind is "inheritance is the base class of evil" lol.

    • @stephenhowe4107
      @stephenhowe4107 3 роки тому +3

      Not at all. It is useful for modelling a real life situation

    • @SamTheSciencerAtheist
      @SamTheSciencerAtheist 3 роки тому +1

      That's why Rust doesn't have it.

    • @SamTheSciencerAtheist
      @SamTheSciencerAtheist 3 роки тому +1

      ​@@mattmurphy7030 Sorry, man. I disagree with you. Every time I saw inheritance and casting used in a company, it lead to disaster. Heavy inheritance usage assumes that models are rigid and will never change, and assume that things that look alike will always be alike, and people are "good" at identifying patterns, which makes them assume that things are the same, and assume that if it walks like a duck, then it's a duck, until you face a flying goat in your program and your whole design model is screwed. All the time, we hear "use composition instead of inheritance", and there's a reason for it. The only time where inheritance is useful is when you want to use it as an interface, and Rust offers that. To me, that issue, 349, sounds like developers used to making bad designs, and are complaining that they can't do these bad designs anymore. Like... how can you see someone asking for a "downcast" and still not think it's a bad idea? Apparently people crave complaining about dynamic_cast, and rust isn't giving them that chance.

    • @SamTheSciencerAtheist
      @SamTheSciencerAtheist 3 роки тому

      @@mattmurphy7030 it's "controversial" only because people got used to it, for the last 50 years, not because it's a great idea. It was a good idea back then when programs were very simplistic and computer modelling was a new thing, not in this decade.
      And if UE uses inheritance successfully, it doesn't mean at any capacity that this is the only way, nor have I said that inheritance cannot be useful, but what I said is that inheritance can be useful for the short term, until things break, and then you patch the patch 559 times until your code becomes legacy code that falls under its own weight or increase the cost significantly. Again, keeps happening, even if there are exceptions, but that's the rule it seems.
      And notice something, it's not that inheritance is inherently bad. The problem is that programs are almost never static. There's a reason why waterfall is dying and everyone is chasing scrum and agile. The problem with inheritance is that it assumes you know everything at the time of designing the code, which is not even close to true and leads to high code coupling based on coincidences, and ironically, was kind of OK 50 years ago with waterfall. It's the wrong thing to assume nowadays. That's the issue with inheritance.

    • @NicolaiSyvertsen
      @NicolaiSyvertsen 3 роки тому +1

      @@SamTheSciencerAtheist Some people cannot imagine a better way of doing something. Like at all. It simply never dawns on them.

  • @DrGreenGiant
    @DrGreenGiant 3 роки тому +1

    Been waiting for this topic. I've had to overcome the diamond problem a few times. Does virtual inheritance cause a vtable? Or is it all sorted out at compile time

    • @sorakatadzuma8044
      @sorakatadzuma8044 3 роки тому +1

      Depending on the implementation, according to others in the comments, and from my own understanding: the instance ends up having to track an extra pointer to the true base class, which should be first in the instance memory. Next would be the vtable for that shared base, then all it's memory. Then it would be the vtable for one of the inherited classes and all it's components and then the next class before the fully derived class. So in the most roundabout way of answering; yes, it should cause a vtable. What impact it has on the application should be benchmarked, but if the standard isn't afraid to use it in iostream then it must not be completely evil 😂

    • @DrGreenGiant
      @DrGreenGiant 3 роки тому +1

      @@sorakatadzuma8044 thank you very much :)

  • @benjaminshinar9509
    @benjaminshinar9509 3 роки тому +1

    in my opinion, the weirdest (most annoying) part of this situation is that we defy the open close principle.
    we have intermediate1 and intermediate2 and they work fine, but to implement derived :intermediate1, intermediate2 we need to go and change them.
    which means that any other derived classes that use them are now under suspicions.
    question:
    what would happen if I marked all my inherited classes as virtual inheritance?

    • @DrGreenGiant
      @DrGreenGiant 3 роки тому

      I wondered this too. It almost seems logical to make all inheritance virtual unless you have a specific need not to.
      It also begs the question about thread safety and having to make everything in base atomic or whatever since you have multiple routes to get at it

    • @yash1152
      @yash1152 Рік тому

      > _"but to implement derived :intermediate1, intermediate2 we need to go and change them."_
      > _"what would happen if I marked all my inherited classes as virtual inheritance?"_
      yeah, i had exactly same grudge, and consequently same question. tbh, i really think i will not be passionate about cpp...

  • @DaveMackenzie
    @DaveMackenzie 3 роки тому

    I loved learning about multiple inheritance years ago and THEN being told, "It's possible, but if you find yourself needing it, maybe take a step back to the diagram-design level before you proceed." So, I've just avoided it. Diamond structures bother me. Trees shouldn't do that. I'd love to see an example of where it is actually a clever solution.

    • @cppweekly
      @cppweekly  3 роки тому

      I have absolutely no problem with multiple inheritance, but diamond structures are generally terrible. I'm pretty sure I actually say that in the video, no?

  • @sephirostoy
    @sephirostoy 3 роки тому +1

    I've used it sometimes with interface base classes. Something like:
    // Interface (abstract classes):
    class IBase { };
    class IDerived : public virtual IBase { };
    // Concrete implementations:
    class Base : public virtual IBase { };
    class Derived : public Base, public IDerived { };
    The only thing that bother me is where the virtual keyword is put. I guess it's for technical reasons but it doesn't make sense from logical point of of view. In my case above, the only class which is "aware" of the multiple inheritance is Derived. So to me it would make more sense to put the virtual keyword in its inheritance:
    class Derived : public virtual Base, public virtual IDerived { };

    • @leleo53000
      @leleo53000 3 роки тому

      whether it uses a normal or virtual inheritance has an impact on the vtable and class layout, and since you want the same type to be the same everywhere, it requires every intermediate "leaf" of your inheritance tree to be marked as needed

  • @eLBehmo
    @eLBehmo 3 роки тому

    Next video is about order of initialization and virtual destructors in overly complex diamond inheritance constructs?

    • @cppweekly
      @cppweekly  3 роки тому

      If anything next episode is just a single title "avoid virtual inheritance and diamond hierarchies."
      30 seconds of the title screen :D

  • @KeinNiemand
    @KeinNiemand 6 місяців тому

    But what happens if thia ia combined with virtual funnction let's base has a virtual function f that both intermidiate1 and intermindiate2 derive from (both inheriting virtually), what function will you call then just the base version or is it still considerd abigoua?

    • @cppweekly
      @cppweekly  6 місяців тому

      Did you test it to find out?

  • @ibrozdemir
    @ibrozdemir 2 роки тому

    i wonder if people use these kind of things.. virtual multiple inheritance

    • @cppweekly
      @cppweekly  2 роки тому

      I have seen it used. At the time it was the only solution we could find (needed for subclassing from QObject + another type)

  • @nmmm2000
    @nmmm2000 3 роки тому

    I was wonder, can we do patterns other than a diamond? like two separate virtual bases? hope you know what I mean :)

    • @ecosta
      @ecosta 3 роки тому

      In C++? Surely you can do it. You can have a full mesh of base and intermediates, if your sanity (and coworkers) allows it. :)

    • @nmmm2000
      @nmmm2000 3 роки тому

      @@ecosta But how? can you show me example code?
      suppose we have virtual Base, inherited to A1 and A2 and another virtual Base of same type, inherited to B1 and B2
      or I need to use two "empty classes" so two virtual Base to be of different types?

    • @ecosta
      @ecosta 3 роки тому

      @@nmmm2000 I can't post links here and I'm not sure if I can describing it with just text, but I did some experiments in Compiler Explorer, and I was able to navigate using a syntax like "derived.Int1::Base1::value". Worst case I had to introduce a temp ref, like "Int1 & i = derived; i.Base1::value".

  • @szymoniak75
    @szymoniak75 3 роки тому

    What is the tool that allows you to draw on the screen called?

  • @georgepetrosyan4589
    @georgepetrosyan4589 3 роки тому

    Dimond problem!

  • @eboyarski
    @eboyarski 3 роки тому

    Click-baity title. Also, I would have liked you to show how virtual base classes are implemented by the compiler.

    • @cppweekly
      @cppweekly  3 роки тому

      Not really click-baity, at least 75% of the people who responded Twitter discussion about virtual inheritance thought that I was referring to virtual functions.

    • @eboyarski
      @eboyarski 3 роки тому +1

      @@cppweekly I still think it would be cool to show how virtual base classes are implemented in a future video though.

  • @simonfarre4907
    @simonfarre4907 3 роки тому

    For me, the most obvious question becomes, why is this valid C++ code and shouldn't these things be removed from the language entirely. C++ after all, is a language that strives for efficient and correct code.

    • @King0Mir
      @King0Mir 3 роки тому +4

      C++ doesn't distinguish between classes and interfaces, so multiple inheritance is a more generic solution that has other uses. But with multiple inheritance of classes with data members, you need to decide if you want to share the base class or not. So C++ provides both ways of doing it, with the more expensive thing being the more verbose and opt-in.

    • @larswadefalk6423
      @larswadefalk6423 3 роки тому

      I think it's a sign of a structure that may be going in the wrong direction. Yet still it can be useful in rare cases and I don't like to blaim a language for being generic and flexible.
      That's why we have people to learn us from their mistakes on how to do things the right way.
      Think of this example, java forbids operator overloading as it was considered by the creator to be a "bad thing". But in actual cases things means different depending on the context.
      Even math itself has operator overloading implicitly, compare for instance matrices between simple scalar values.
      Therefore it makes absolute sense to have a notion of operator overloads depending on the type, as long as the semantics make sense.