I'm actually going to try and leave this code free, for your benefit, because both headers have roughly 50+ lines each. Not that I'm trying to insult your ability to read or "hide" my code, but because I don't know where to begin/what to paste. If you want it, ask and I will, but for simplicity...
Basically, I'm trying to play with C++ (what I should have been doing all along) instead of bookworm it, and remembering back through Programming Principles and Practice, I decided I wanted to work on inheritance and polymorphism. I wanted to make a framework for a game that had characters because... well, it's funner than class B:public A and whatnot, and is a more "practical" program.
At this moment I have a Human class derived from a Character class which - at least I think, and I'd love your opinion - was created solely for the purposes of listing basic stats that ANY creature would have (and could have been called that just as well). I'm to the point now I want to make it a pure base class, but I don't know how I should approach that, and as I'm to understand there are options:
- Pure virtual functions
- Protecting the constructor(s)
I'm also to understand pure virtual functions are the preferred method, so I'd like to follow tradition, but I don't know how many I should provide, and even WHAT they should be.
I was thinking that I wanted to make an easy way to print statistics, so I created two output_attributes functions(), one for cout, and one for any ostream. All good, but SHOULD one of those/both of those/EVERY function be pure virtual? Should the other functions (operators mostly, but of course I have get() functions for individual stats) be virtual in ANY capacity?
I realize virtual functions, polymorphism, and inheritance are important aspects, so I just want to do it right and not learn bad habits. Also, it's excellent (and surprisingly fun) practice. I AT LEAST feel good about the character base class. I feel like I made a good call on that - if I want to make a dwarf or an elf or a hobbit or just anything Tolkien ever thought of, the Character class is a solid start, but everything else I'm iffy on.
Also, if you INSIST on seeing the code (and I haven't been forthright - another reason is I'm slightly embarrassed by my code) then I'll oblige you in all its lack of glory, complete with comments I made for myself... and yes, I DO write comments to myself in the manner you'll see in Character.h:
//I want to be VERY clear that Character is intended to be a base class, but I'm not certain
//how/where to implement that concretely. Pure virtual functions seem the likely and
//popular solution, but there is always protecting the constructor.
//That also brings up, "What should and shouldn't be protected?" Also, if we're using
//virtual functions (polymorphism), what/how many members should be virtual?
#pragma once
#include <string>
#include <iostream>
class Character {
public:
Character();
Character(short strength, short vitality, short dexterity);
Character(const Character&) = delete; //Copy constructor disabled
~Character();
short get_str() const { return str; }
short get_vit() const { return vit; }
short get_dex() const { return dex; }
int get_hp() const { return hp; }
//Managing additions to attributes made easier
virtualvoid output_attributes() const;
virtualvoid output_attributes(std::ostream& os) const;
virtual std::ostream& print_information(std::ostream& os) const;
virtualvoid print_information() const;
booloperator==(const Character& ch);
booloperator!=(const Character& ch);
//I THINK THESE ARE LIKELY USELESS_________________________________________
virtual std::ostream& operator<<(std::ostream& os);
virtualvoidoperator<<(const Character ch);
private:
//Character(const Character&); //IF PRIVATE, this also prevents copying.
//Should implement a luck stat later.
short str;
short vit;
short dex;
int hp;
};
booloperator==(const Character& a, const Character& b);
//bool operator!=(const Character& a, const Character& b); //Perhaps a bad idea
void char_compare(const Character& a, const Character& b);
constexprshort def_params{ 5 }; //Just because the book at this point uses them.
NOTE: I haven't updated Human for printout as I did character. Also yes, I'm including constructor/destructor output to see how it all comes together. Also yes, I did it for virtual functions as well to see if they were being overridden. No, I'm still not 100% convinced I'm using inheritance and overriding them correctly.