Skip to content

Instantly share code, notes, and snippets.

@hallfox
Created September 24, 2017 19:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hallfox/64c1603ce6c6c926af94096b525befc7 to your computer and use it in GitHub Desktop.
Save hallfox/64c1603ce6c6c926af94096b525befc7 to your computer and use it in GitHub Desktop.
Example of proper encapsulation in C++
#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