C++ without classes
This commit is contained in:
parent
7cf5fbf843
commit
59bdeb93ac
1 changed files with 88 additions and 0 deletions
88
content/programming/cxx-without-classes.tree
Normal file
88
content/programming/cxx-without-classes.tree
Normal file
|
@ -0,0 +1,88 @@
|
|||
%% title = "C++ without Classes"
|
||||
|
||||
- one thing I often see in people's code in C++ is putting _everything_ into a class.
|
||||
|
||||
- there's nothing wrong with putting code that actually, y'know, _uses the class_, in the class, but it irks me when I see things like helper functions and other implementation details being in the class.
|
||||
|
||||
- private functions have the unfortunate consequence of being part of the public header, even though they are implementation details!
|
||||
this means if you edit them, you have to edit both the .cpp implementation file, as well as the .h header.
|
||||
|
||||
- which is precisely what C++ without Classes is about.
|
||||
since updating method signatures is a pain in the ass... just don't do it!
|
||||
|
||||
- declare all your fields public, and let `static` functions within your `.cpp` file work the magic.
|
||||
|
||||
- and here you might say: "but I don't _want_ to have these fields public! it breaks encapsulation!"
|
||||
to which I respond: so make your data structure private!
|
||||
|
||||
- example of C++:
|
||||
|
||||
#### world.h
|
||||
|
||||
```cpp
|
||||
struct World
|
||||
{
|
||||
// ... fields ...
|
||||
|
||||
void update(const Update_Context& context);
|
||||
|
||||
private:
|
||||
void update_aims(const Update_Context& context);
|
||||
};
|
||||
```
|
||||
|
||||
#### world.cpp
|
||||
|
||||
```cpp
|
||||
void World::update(const Update_Context& context)
|
||||
{
|
||||
update_aims(context);
|
||||
}
|
||||
|
||||
void World::update_aims(const Update_Context& context)
|
||||
{
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
- example of C++ without Classes:
|
||||
|
||||
#### world.h
|
||||
|
||||
```cpp
|
||||
struct World
|
||||
{
|
||||
// ... fields ...
|
||||
};
|
||||
|
||||
void update(World& world, const Update_Context& context);
|
||||
```
|
||||
|
||||
#### world.cpp
|
||||
|
||||
```cpp
|
||||
static void update_aims(World& world, const Update_Context& context)
|
||||
{
|
||||
// ...
|
||||
}
|
||||
|
||||
void update(World& world, const Update_Context& context)
|
||||
{
|
||||
update_aims(world, context);
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
- suddenly, the publicly available part of `world.h` has gotten smaller---there's one method less.
|
||||
the implementation detail `update_aims` does not leak into the header; we don't have to update the signature in two places if we ever want to change it, and it does not cause a recompilation if we edit it.
|
||||
|
||||
- I took the `update` method out of the struct to signal the lack of coupling.
|
||||
_anyone_ can do what `update` does; it doesn't matter.
|
||||
every function is at the same level as the struct itself.
|
||||
|
||||
- in my own code, outside this contrived example, I also put functions related to a data structure in a namespace---in this case, `update(World&, const Update_Context&)` would be `world::update(World&, const Update_Context&)`.
|
||||
this is purely a stylistic preference---I like the extra explicitness over leaning on overloads.
|
||||
|
||||
- I've been enjoying this style a lot.
|
||||
it takes edge cases like `this` out of the language, and results in simpler, more easily editable code.
|
||||
so I wholeheartedly recommend giving it a try!
|
Loading…
Add table
Add a link
Reference in a new issue