The Pointer to Implementation (pImpl) idiom in C++

Поделиться
HTML-код
  • Опубликовано: 29 сен 2024

Комментарии • 32

  • @maxprex
    @maxprex 3 года назад +14

    That was beautifully explained. I especially love how you enunciate the key parts that often cause confusion. Thank you!

    • @platisd
      @platisd  3 года назад +4

      Thanks! I sometimes fear that some viewers might find the slower enunciations awkward, so it's good to hear that others like them. 😅

  • @PflanzenChirurg
    @PflanzenChirurg 3 года назад +1

    I2C in reality means i square c :D

  • @arnoldtharrington2087
    @arnoldtharrington2087 Год назад +2

    Very clear explanation of pimpl. I'm adding you to my subscriptions.

  • @mashtonish
    @mashtonish 2 месяца назад +1

    I appreciate these short tutorials for offering a different perspective on certain idioms or principles with direct messaging, instead of some hook or extremely fancy presentation. Although the videos require pausing (for myself) in some parts to think through them a little more, the presentation is short enough so that I don't feel trapped by having it sit in a browser tab for a while until I can commit to it.
    Thanks.

    • @platisd
      @platisd  2 месяца назад

      @@mashtonish thanks for the positive feedback! 😄

  • @sqlexp
    @sqlexp 2 месяца назад +1

    This is a workaround for the inefficiency and deficiency of the header inclusion mechanism. I think C++ module will make pimpl obsolete.

    • @platisd
      @platisd  2 месяца назад +1

      I haven't fully thought it through since I haven't used modules yet, but something tells me there might still be some obscure use case for it. 🤔😫

  • @KobiCohenArazi
    @KobiCohenArazi 3 года назад +2

    Gyro::~Gyro() = default; should also work (instead empty impl { })

    • @platisd
      @platisd  3 года назад +1

      It would indeed! 👍

    • @KobiCohenArazi
      @KobiCohenArazi 3 года назад

      @@platisd great video btw. keep it up! :)

  • @jgmccabe
    @jgmccabe Год назад +1

    I believe you mentioned that this is a technique appropriate to specialisation at link-time, i.e., if you wanted to use a SPI comms interface instead of I2C for an application, that would require the source code for Gyroscope::GyroscopeImpl in Gyroscope.cpp to be physically different. Is that correct? If you wanted to decide, at run-time, whether to use SPI or I2C, would you extract an interface, say CommsDevice, implemented by I2cCommsDevice and SpiCommsDevice with a pointer to the interface held in the GyroscopeImpl class, and passed in via, e.g. its constructor (or a setter function)? (Sorry to use Java terms so much, but they are clearer than C++ - 'interface' - > 'pure virtual base class' etc 😂).

    • @platisd
      @platisd  Год назад

      I am a bit confused because `Gyroscope.cpp` doesn't include any `GyroscopeImpl` and then you lost me about the part where a pointer is being passed via a setter or constructor.
      I suspect passing anything via the constructor/setter will defeat the purpose of hiding the implementation, but I could be misunderstanding you.
      How about this: RUclips isn't the right platform for such discussions, what if we take it on GitHub instead?
      Could you please open an issue in the repo (github.com/platisd/cpp-pimpl-tutorial) add any code snippets or links to files you think are necessary and then I promise you we will get to the bottom of this. :)

  • @anthonymonterrosa4383
    @anthonymonterrosa4383 3 года назад +1

    At the end you say you prefer not to use the pattern yourself. I think it could be enlightening to use listeners to understand why. Is it because of link-time optimization? Because it's ugly? Because boilerplate?

    • @platisd
      @platisd  3 года назад +3

      Great question Anthony!
      I didn't elaborate further on that because I wanted to keep the video mainly about pImpl and not its alternatives.
      I would only use the idiom if I was distributing a library and I wouldn't want (or it wouldn't be feasible) software the depends on it to have to be recompiled every time I update inner implementation of the library. In other words, if I'd go for pImpl if wanted to keep the ABI of my library stable across updates.
      If that wasn't the case, I would prefer some kind of polymorphism, static or runtime. I would use polymorphism instead because I find pImpl more complicated to use & understand as well as relatively less testable.

  • @guitarheroua
    @guitarheroua 3 года назад +1

    Nice explanation! I really like your videos and glad that found your channel. Thanks for your work!

    • @platisd
      @platisd  3 года назад

      Thanks a lot Andriy! :)

  • @aj-uo3uh
    @aj-uo3uh Месяц назад

    Not clear what you do with SpiGyroscope. How is it related to the previous classes. UML would be handy.

    • @platisd
      @platisd  Месяц назад

      The `SpiGyroscope` example is there to show how you could still use dependency injection (DI) and have an easily testable class that contains your business logic, within `pImpl`.
      This example was added because `pImpl` hides dependencies, while with DI we usually let the user provide them, so it may not obvious if you'd still want to write unit tests with easily mockable dependencies.
      In other words, this last example is related to the rest only by it also using the `pImpl` pattern.

    • @aj-uo3uh
      @aj-uo3uh Месяц назад

      @@platisd So do you mean that GyroscopeImpl will have a pointer to SpiGyroscope?

    • @aj-uo3uh
      @aj-uo3uh Месяц назад

      Oh now I see it. Indeed GyroscopeImpl contains a member of type SpiGyroscope. Never mind.

    • @platisd
      @platisd  Месяц назад +1

      @@aj-uo3uh kind of, but not really. The `GyroscopeImpl` (which happens to be instantiated as a pointer) contains a `SpiGyroscope` as a member variable.
      Have you checked the GitHub repository in the description by the way?
      Perhaps it will become clearer: github.com/platisd/cpp-pimpl-tutorial/blob/master/private/src/SpiGyroscopeImpl.cpp

    • @aj-uo3uh
      @aj-uo3uh Месяц назад

      @@platisd Thanks, I was adding an addition at the same time of your answer. Another thing I don't understand is the incomplete type errors. I read chapter 22 of Scott Meyers c++11. I understand that when you don't write the destructor the compiler will generate it and make it inline. But client code of Gyroscope will include the .h file and see the forward declaration. Why can't the compiler, linker, not look the definition up of the impl class? Scott doesn't explain this.

  • @NickEnchev
    @NickEnchev 3 месяца назад

    Surprisingly good video!

  • @juliankandlhofer7553
    @juliankandlhofer7553 3 года назад

    Very interesting. This seems very similar to something like java Interfaces, where a consumer just knows about the interface and nothing about the implementation, right?

    • @platisd
      @platisd  3 года назад +1

      Well, kind of. There are JAVA-like interfaces (i.e. "pure abstract classes") in C++ as well, so those would be the direct equivalent. pImpl allows compatibility on a binary level as well, i.e. an even looser coupling. So if component "A" depends on a common interface "Foo" that is implement by "BarFoo" and everything is compiled together, then if "BarFoo" changes then "A" has to be recompiled.
      On the other hand, if BarFoo was hidden behind the pImpl idiom, you wouldn't have to recompile "A" or you could even switch the library out on your filesystem completely, with something else. This is the most common use case for pImpl as far as I know. You can let your user/customer depend on your library (e.g. a .so or .dll file) and if you make changes to it, you can switch it out to another one as long as you haven't changed the public interface.

    • @juliankandlhofer7553
      @juliankandlhofer7553 3 года назад

      @@platisd Ahh so ABI stability. Thanks for explaining!

  • @dekadebashish
    @dekadebashish 3 года назад

    Loud and clear

  • @anirbansengupta8465
    @anirbansengupta8465 3 года назад

    Thanks for making wonderful contents

  • @mashtonish
    @mashtonish 3 месяца назад +2

    rampant acronyms, "code smells", pimpl... sometimes the things people come up with are gross.