3 ms·
> It does not work on a field, but on the whole struct. struct PrivateFieldsOfMyShinyClass; struct MyShinyClass { int somePublicData;
by Joker_vD 3y ago
> It does not work on a field, but on the whole struct.
struct PrivateFieldsOfMyShinyClass;
struct MyShinyClass {
int somePublicData;
double morePublicData;
struct PrivateFieldsOfMyShinyClass *p;
};
> malloc isn't possible, but neither are copies by value, sizeof() breaks
Those are implementation details which are deliberately being hidden.
> Completely incompatible with inlining code.
They are as incompatible with code inlining as public/private modifiers in C++ are. That is, LTO is your best friend here. Also, have you ever tried to maintain binary compatibility with several versions of a third-party C++ library that keeps adding/removing private fields to/from its classes?
- jstimpfle 3y agoHiding members in this way is only possible with pointer indirection, which isn't satisfying. However, having only a boolean private/public access state isn't generally satisfying either. It often leads to violation of the principle of separation of concerns when all the functions (methods) acting on certain "private" fields need to live in the same class. In simple classes, like std::vector, it's possible to get away with private. But in many cases that are more complex than that, it seems to me that the best approach is still to expose the data and to be just very clear about the exact purpose of each member.
- gjulianm 3y agoThe code sample still isn't equivalent. Now you have yet another pointer, which implies another allocation, another source of possible memory leaks and mistakes, and a separate memory space that will hurt the cache. > Those are implementation details which are deliberately being hidden. I know they're being hidden deliberately, but in C++ "private" doesn't break malloc (new), copies by value or sizeof. Or stack allocation, to add to the list. > They are as incompatible with code inlining as public/private modifiers in C++ are. That is, LTO is your best friend here. public/private aren't incompatible with inlining in C++. That is, you can call class functions that access private members and the compiler can inline those functions. Also, LTO is not always enabled by default, and doesn't always inline the things you want it to inline. > Also, have you ever tried to maintain binary compatibility with several versions of a third-party C++ library that keeps adding/removing private fields to/from its classes? I mentioned binary compatibility as one of the reasons one might want to do this. However, if you have a third party that doesn't care about API compatibility I doubt struct fields are the only thing they're going to change constantly.
- skribanto 3y agoMaybe have your public fields defined as a second struct, and then you can cast the pointer to your struct to the concrete struct that has all the public fields. This has the restriction that all public fields must be at the start, and you must make sure to maintain the same order between the two structs. At this point though, I think I honestly would prefer setters/getters. struct MyClassPublic { int x; int y; ... } /* using it */ MyClass *myclass = myclass_create(); ((MyClassPublic *)myclass)->x = 5;
- dfawcus 3y agostruct public_stuff { ... } struct private_stuff { struct public_stuff public; ... } struct public_stuff *make_public(/* ... */) { struct private *prv = malloc(sizeof *prv); /* ... */ return &prv->public; } Then when passed in to functions, cast the passed in struct pointer to the private one. The public struct doesn't even have to be at the start if one make appropriate use of offsetof and ensuring valid alignment. Nothing new under the sun...