A fully grown Function ObjectTrail Index | Objects 2 | Fully Grown Object Let's take the Function Object, and apply to it the lessons about protection: /** * Objects: full grown functor class * * Note that this is more complicated... * It's the price to pay for full control, * and you may want to pay it only when necessary, * that is, when your program grows and you risk losing control * of its details, or when you expect someone to use your * code as a "black box", without checking much... */ #include <iostream> #include <cmath> /** * Full grown class. * - Has access control to different parts (public, private) * - uses "setter" and "getter", to give controlled access * to private member data, like eg if(v>0) ... * The only difference between "class" and "struct" is * that "struct" defaults to public, and "class" to private. * But it's good style to always specify them anyway in class, * and to use struct only for all-public object definitions. * * It's also recommended to put public members on top, * since from outside the class should be a "black box", * and its users should only care about the "public interface" */ class Function { public: Function(double newk1,double newk2): k1(newk1), k2(newk2) {}; double operator()(const double x) const { return sqrt(k1)*x+k2*x*x; } /** * "getter" method, read only access */ double getK1() const { return k1; } /** * "setter" method for k1. * In this way I can make sure that the parameter * has a valid value for sqrt ! */ void setK1(double v) { if (v>0) k1=v; } double getK2() const { return k2; } void setK2(double v) { k2=v; } private: double k1; // can't touch this from outside double k2; }; /** * Note that I cannot touch f1.k1 directly anymore.. * I have to use the more verbose getK1() and setK1() */ int main() { Function f1(2.,3.); const double y1=f1(3.); std::cout<< "f1("<<3.<<")="<<y1<<"\n"; { Function f2(4.,5.); const double y2=f2(3.); std::cout<< "f2("<<3.<<")="<<y2<<"\n"; } f1.setK1(-1.); std::cout<< "now f1.k1="<<f1.getK1()<<" f1.k2="<<f1.getK2()<<std::endl; const double y3=f1(3.); std::cout<< "f1("<<3.<<")="<<y3<<"\n"; } You have certainly noticed that the code is longer, more verbose. This is one disadvantage of strictly applying the protection rules. Also, there could be some impact on the performance. Because of these two downsides, you may want to use these data protection techniques only on more sensitive items. On the other side, a full use of these "accessor methods" allows some interesting things, as you can see in the following section. |