5 ms·
> In principle you're right, but the notion that header file exposes just the "interface" is completely false. Sorry, but it is not "completely false". Doing
by jlarocco 8y ago
> In principle you're right, but the notion that header file exposes just the "interface" is completely false.
Sorry, but it is not "completely false". Doing it properly requires a carefully designed interface to hide internal data structures, and splitting out the end user headers from the internal headers, but it works.
> I've never had to deal with pesky header files until I started developing C and it immediately struct me as a royal pain in the ass.
It's like saying, "I've never had to deal with pesky .py files until I started developing Python."
- fermienrico 8y agoHow do you compare .py files with .h files? I am confused as to how you are drawing this analogy.
- jlarocco 8y agoI mean header files are C and C++ source files, so saying you didn't have to deal with them until using C and C++ is a tautology. Likewise, you won't have to deal with .py files until you're using Python.
- fnrslvr 8y ago> Doing it properly requires a carefully designed interface to hide internal data structures, and splitting out the end user headers from the internal headers, but it works. Out of curiosity, how? (If pointers or other mechanisms for memory indirection are allowed then it's pretty easy, so let's agree to ban those.) Not a rhetorical question, despite the parenthetical.
- jlarocco 8y ago> Out of curiosity, how? (If pointers or other mechanisms for memory indirection are allowed then it's pretty easy, so let's agree to ban those.) Here's one popular way to do it in C++: https://en.cppreference.com/w/cpp/language/pimpl https://en.cppreference.com/w/cpp/language/pimpl I guess my tongue in cheek response to your parenthetical would be to ban the use of hidden internal data structures ;-)
- creatornator 8y agoYou can split "secret" data structures into another header, and them simply not give that secret header to the customer. If you give the binary and a header with some structures missing, the user can still use whatever you did give them.
- cbuq 8y agoFor global or namespace functions you can hide the implementation in the .cpp file. Doing the same with objects require pointers to hide the details of any private members. A common pattern is called Pointer to IMPLemenation (PIMPL). Not sure why we need to exclude pointers? In c++14 this is very much simplified with the use of unique pointers. std::unique_ptr<Foo> make_foo(...);
- fnrslvr 8y agoBecause I want full encapsulation without giving up by-value semantics. I want my clients to be able to take objects of some opaque record type that I've defined, and put them entirely on the stack, or in some contiguous block of memory entirely of their making, without ever getting to know the constituent fields of the record. I want it all, I want to have my cake and eat it too. When the parent (er, great grandparent?) says their parent is wrong to deny that headers only reveal the interface, I think it's a little disingenuous to base that on an unrevealed assumption that PImpl is in play. PImpl is basically the the idiom that begot Java. One reason I might opt for C++ over Java, is a desire for finer control over the location of memory -- but it's important for me to know that to actually get that, I'll probably have to sacrifice information hiding. It's a trade-off. Yes, on some level it's better to have the option to make that trade-off, but the product here is "encapsulation or value semantics", not "encapsulation and value semantics". Mind, I'm not a C++ developer. Maybe these days link-time heroic optimization makes the "right" decisions and collapses these kinds of indirections in all the sorts of situations you'd want it to. I write a lot more Java, and my understanding is that HotSpot gets up to a lot of heroics pertaining to this stuff these days -- I've noticed HotSpot will churn through a workload involving processing a collection of records far more quickly if you can arrange for it to stream through an array, even if you'd expect the records to be scattered randomly throughout memory.
- ryl00 8y ago> I want it all, I want to have my cake and eat it too. Conceptually this should be possible with some preprocessor/header tinkering; something like: private.h: struct Bar { double x; double y; }; #define BAR_DEFINED public.h: #ifndef BAR_DEFINED struct Bar { char opaque[16]; }; #endif struct Foo { Bar bar; }; consumer.cpp: #include "public.h" private_implementation.cpp: #include "private.h" #include "public.h"