CodeProject
A well encapsulated design makes only the minimum necessary parts of a class public
(public
or protected
). In other words, everything should be private
by default and make things public
(or protected
) only if absolutely necessary.
In C++, one tool for this is to implement parts of your class as non-member non-friend functions. These functions should be put in a namespace so, they don’t litter the global namespace. If you have a class Widget, then usually people define a WidgetHelper
namespace in which they put the Widget
class and also its helper functions:
class Widget {
public:
Widget() : width{}, height{} {}
void setWidth(int w) { width = w; }
void setHeight(int h) { height = h; }
private:
int width;
int height;
};
namespace WidgetHelper {
void setSize(Widget& o, int w, int h) {
o.setWidth(w);
o.setHeight(h);
}
}
int main() {
auto w = Widget{};
WidgetHelper::setSize(w, 10, 20);
return 0;
}
A cleaner way is to use something I call the Widget::O
idiom. Here it is how the above code looks like using the Widget::O
idiom:
namespace Widget {
class O {
public:
O() : width{}, height{} {}
void setWidth(int w) { width = w; }
void setHeight(int h) { height = h; }
private:
int width;
int height;
};
void setSize(O& o, int w, int h) {
o.setWidth(w);
o.setHeight(h);
}
}
int main() {
auto w = Widget::O{};
setSize(w, 10, 20); Widget::setSize(w, 30, 40); return 0;
}
The Widget::O
idiom helps you in keeping all the functions and data related to Widget::O
in the same Widget namespace, regardless of whether they are members or non-members. With this idiom, you can use also use ADL (Argument Dependent Lookup) if you prefer when calling the non-member functions.