namespace option_1 { /* * Friend class controls instantiation. Is only one with write access to members */ class Controller; class Model { int _a, _b; Model() = default; public: int a() const { return _a; } int b() const { return _b; } friend class Controller; }; class Controller { Model _m; public: Controller() : _m() { _m._a = 1; _m._b = 2; } const Model* model() const { return &_m; } }; int test() { Controller c; const Model* m = c.model(); return m->a(); } } namespace option_2 { /* * Instantiation is not controlled but pointless so who cares? * Controller returns const pointer to Model so Controller is still only * one with write access to the only genuine Model object. * To avoid accidental misuse, copy construction of Model is denied. */ class Controller; class Model { int _a, _b; public: Model() = default; Model(const Model&) = delete; Model& operator=(const Model&) = delete; void a(int a) { _a = a; } void b(int b) { _b = b; } int a() const { return _a; } int b() const { return _b; } }; class Controller { Model _m; public: Controller() : _m() { _m.a(1); _m.b(2); } const Model* model() const { return &_m; } }; int test() { Controller c; const Model* m = c.model(); return m->a(); } } namespace option_3 { /* * A weird little trick: Abuse private inheritance to hide the model in the * inheritance hierarchy of the controller. * I wouldn't consider this good design but it's a neat trick for corner * cases. */ class Model { protected: int _a, _b; Model() = default; ~Model() = default; public: Model(const Model&) = delete; Model& operator=(const Model&) = delete; int a() const { return _a; } int b() const { return _b; } }; class Controller: private Model { public: Controller() { _a = 1; _b = 2; } const Model* model() const { return this; } }; int test() { Controller c; const Model* m = c.model(); return m->a(); } } namespace option_4 { /* * Cleaner version of option_3. Modifiers for Model are restricted to a * subclass that only Controller can access. */ class Model { protected: int _a, _b; Model() = default; ~Model() = default; public: Model(const Model&) = delete; Model& operator=(const Model&) = delete; int a() const { return _a; } int b() const { return _b; } }; class Controller { class MutableModel: public Model { public: void a(int a) { _a = a; } void b(int b) { _b = b; } }; MutableModel _m; public: Controller() { _m.a(1); _m.b(2); } const Model* model() const { return &_m; } }; int test() { Controller c; const Model* m = c.model(); return m->a(); } }