5 ms·
Let's use C and C++ as an example. What does the code look like? myobj.cool_func(1,2,3); // C++ cool_func(myobj, 1, 2, 3); // C Is this better? If y
by fnord123 6y ago
Let's use C and C++ as an example. What does the code look like?
myobj.cool_func(1,2,3); // C++
cool_func(myobj, 1, 2, 3); // C
Is this better?
If you use a vanilla C++ style class then the class definition is in the header. All changes to the class require a recompilation and break the ABI of the class. This means you basically cannot release patch versions of your library because consumers cannot link against it if they have the old headers.
Contrast with C where you would forward declare a struct in the header and pass that around while the definition is hidden in a .c file. This means changes to the size of the structure don't matter because all calling code ever sees is a pointer. (True data hiding!) It's called an opaque pointer and many many libraries use this pattern. e.g. libcairo.
There is then a pattern to do this in C++ called pimpl:
https://en.cppreference.com/w/cpp/language/pimpl https://en.cppreference.com/w/cpp/language/pimpl
This solves it for C++ but the alleged convenience is gone because now you're coding C++ with the supposed convenience but still your class implementation has to trampoline all the calls to the pimpl which is an extra function call (if you're writing C or C++ this might matter).
But RAII, though. Not having [standardized] RAII sucks.
- nicoburns 6y ago> This means you basically cannot release patch versions of your library because consumers cannot link against it if they have the old headers. This is pretty much only a problem in C/C++ though. Everyone else is using static linking (which you can of course also do in C++), or a VM of some form. IMO relying on a library having stable ABI is a bit of anti-pattern. It's like relying on the implementation details of a function/class rather than it's API: sometimes it's necessary, but it should be avoided if possible.
- fnord123 6y agoJava has the possibility of maintaining ABIs as well. And I imagine that's what .Net assembles are about too. I think you're heavily over stating reliance on libraries having stable ABIs as an anti-pattern. If a mistake is made in the ABI promise, can it get hairy? Absolutely. If you work on an application and are somewhere in the middle of it and need to recompile it to test a fix, do you want to wait for the compilation of the entire application to test it? Obviously not.
- jcelerier 6y ago> If you use a vanilla C++ style class then the class definition is in the header. All changes to the class require a recompilation and break the ABI of the class. definitely not all, only things that change the layout. adding a non-virtual method does not break ABI at all for instance. > Contrast with C where you would forward declare a struct in the header and pass that around while the definition is hidden in a .c file. This means changes to the size of the structure don't matter because all calling code ever sees is a pointer. (True data hiding!) It's called an opaque pointer and many many libraries use this pattern. e.g. libcairo. Does this have a point in 2020 ? Good modern practice (c.f. Rust, etc) is to ship LTO'ed mostly-static binaries. Such hiding is only relevant for legacy things such as what Linux distros obstinates themselves in doing for their userspace - hopefully in a few years everyone will switch to snap / flatpack / appimage to finally reach a sane application distribution model on Linux. I'd definitely say PIMPL is 100% an anti-pattern in every possible case. It forces more memory allocations, and makes it much harder to hack your way out of things when it's 3AM and everything is crashing and you have 5 minutes to fix things before heads start to roll.
- fnord123 6y ago> only things that change the layout. adding a non-virtual method does not break ABI at all for instance. Yes, you are correct. The point was that C code can keep the ABI intact through (some) data layout changes but vanilla C++ classes cannot I misstated it. >Good modern practice (c.f. Rust, etc) is to ship LTO'ed mostly-static binaries. That is the state of play now because Rust does not have a stable ABI. I thought one might be coming but maybe no one's working on it. It's unfortunate because it would be really nice to have binary crates with signing. >hopefully in a few years everyone will switch to snap / flatpack / appimage to finally reach a sane application distribution model on Linux. Snap has a while to go before it can be adopted fully. Images are enormous, they take a long time to load, and they don't respect (or don't understand) hidpi settings. I tried to use it for spotify and telegram-desktop and other applications but they just don't work that well. >it much harder to hack your way out of things when it's 3AM and everything is crashing and you have 5 minutes to fix things before heads start to roll. Absolutely but it comes from enormous systems like Windows where changing a library and breaking ABI means recompiling Everything. And these compilation jobs are often 'overnights'.
- Const-me 6y ago> Is this better? Very few professional developers code in vim or notepad. Vast majority of us are using IDEs. IDE knows types of things, type `myobj.` and you'll get a suggestion list with methods of that class callable from the current context. > There is then a pattern to do this in C++ called pimpl There's another useful pattern in C++: struct iObj { virtual ~iObj() { } virtual void cool_func( int a, int b, int c ) = 0; static std::unique_ptr<iObj> factory(); };
- fnord123 6y agohttps://www.cairographics.org/manual/cairo-cairo-t.html https://www.cairographics.org/manual/cairo-cairo-t.html All operations on `cairo_t` have prefix `cairo_`
- Const-me 6y agoThat's doesn't give context for IDE. You can type `cairo_` and get suggestions what may follow, but you can't type `x.` and get suggestions on what you can do with x.
- mrep 6y ago> Very few professional developers code in vim or notepad Notepad++ and vim are the 3rd and 5th most popular development environment according to stack overflows 2019 report [0] and I and many others I know use Vim at least. > IDE knows types of things, type `myobj.` and you'll get a suggestion list with methods of that class callable from the current context. I've never used notepad but Vim absolutely supports omni completion [1]. [0]: https://insights.stackoverflow.com/survey/2019 https://insights.stackoverflow.com/survey/2019 [1]: https://vim.fandom.com/wiki/Omni_completion https://vim.fandom.com/wiki/Omni_completion
- jcelerier 6y ago> Notepad++ and vim are the 3rd and 5th most popular development environment according to stack overflows 2019 report [0] and I and many others I know use Vim at least. in C++ the ratio of ppl I know using an IDE with semantic code completion ability (that is, not rtags but actually using e.g. libclang or something that does understand C++ to some extent for IDE completion) vs "glorified text editors" must be 95/100 using an IDE though.
- im3w1l 6y agoIn C you would do my_lib_cool_func(myobj, 1, 2, 3); so you don't pollute the global namespace excessively. Having it accessed through the object avoids that.