Created
September 24, 2017 19:03
-
-
Save hallfox/64c1603ce6c6c926af94096b525befc7 to your computer and use it in GitHub Desktop.
Example of proper encapsulation in C++
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <wand.h> | |
#include <spell.h> | |
#include <vector> | |
class Wizard { | |
public: | |
// Just showing off a public type alias | |
using SpellBook = std::vector<Spell>; | |
// Constructor, with default wand as parameter | |
Wizard(const std::string &name, const Wand &wand = Wand()); | |
// Other important auto-generated constructors | |
Wizard(const Wizard &wizard) = default; // copy constructor | |
Wizard(Wizard &&wizard) = default; // move constructor | |
~Wizard() = default; // destructor | |
Wizard &operator=(const Wizard &wizard) = default; // copy assignment | |
Wizard &operator=(Wizard &&wizard) = default; // move assignment | |
// Accessor for name, returns a const ref to the member variable | |
// Note that the method itself is marked 'const', all the way on the right | |
const std::string &name() const; | |
// Accessor and setter for wand, a wizard may have multiple types of wands they try to use | |
// Note the setter isn't marked 'const', because we can modify the object through this function like so: | |
// | |
// Wizard wiz("Malaphor"); | |
// ... | |
// wiz.wand() = Wand(Wand::Material::GLASS); | |
// | |
// Here we give a Malaphor the Wizard a glass wand. This "sets" the underlying wand field, but we could | |
// change the implementation of wand() to do something more with Malaphor, although we can't assume that | |
// the property is being set when the method is called. | |
const Wand &wand() const; | |
Wand& wand(); | |
// Same idea, but with the wizard's spellbook | |
const SpellBook &spells() const; | |
SpellBook &spells(); | |
private: | |
// All raw data member fields | |
// Note the underscore after the member name, usually meant to say "this isn't meant for other people to touch" | |
const std::string name_; | |
Wand wand_; | |
SpellBook spell_book_; | |
}; | |
Wizard::Wizard(const std::string &name, const Wand &wand): | |
name_(name), // Initialize name, note we have to set name_ here as it's marked 'const' in the class | |
wand_(wand), // Initialize wand with its copy constructor | |
spell_book_() // Initialize and empty spellbook | |
{} | |
const std::string &Wizard::name() const { | |
return name_; | |
} | |
const Wand &Wizard::wand() const { | |
return wand_; | |
} | |
Wand &Wizard::wand() { | |
return wand_; | |
} | |
const Wizard::SpellBook &Wizard::spells() const { | |
return spell_book_; | |
} | |
Wizard::SpellBook &Wizard::spells { | |
return spell_book_; | |
} | |
// Note that I had to specify Wizard::SpellBook since SpellBook is a type defined in Wizard and the parser isn't aware | |
// we're writing a method for Wizard yet (it won't know until it sees Wizard::spells) | |
// This is annoying and C++11 introduced a new syntax to reduce how annoying that is | |
// I could have written these functions as | |
const auto &Wizard::spells() -> SpellBook { | |
return spell_book_; | |
} | |
auto &Wizard::spells() -> SpellBook { | |
return spell_book_; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment