# OOP demonstration in C++17 using a Pokémon

I want to showcase with as minimal code as possible the basic Object-oriented programming (OOP) principles of Polymorphism, Inheritance, and Encapsulation. I know there are many more principles than just these 3 and even different types of the 3 I've mentioned there. I attempted to implement them all below. I think using Pokémon as an example is a good way to show this, so I've used Castform as my buddy of choice for these examples.

If you believe showcasing more than just Polymorphism, Inheritance, and Encapsulation to evaluate a developers understanding of OOP, please provide comments around this and which additional key principles I should add to my Pokémon example.

Main.cpp

#include <iostream>
#include <string>
#include <time.h>

class Pokemon
{
protected:
int m_dex_num;
float m_catch_rate;
std::string m_type;
public:
Pokemon(int dex_num, int catch_rate, std::string type)
: m_dex_num(dex_num), m_catch_rate(catch_rate), m_type(type) {}

int dex_num() const { return m_dex_num; }
float catch_rate() const { return m_catch_rate; }
std::string type() const { return m_type; }

virtual bool attempt_catch() = 0;
};

class Castform : public Pokemon
{
private:
std::string m_forms[3] = { "sunny", "rainy", "snowy" };
public:
Castform() : Pokemon(351, 11.9, "normal") {}

bool attempt_catch() {
srand(time(NULL));
return (rand() % 100) < m_catch_rate;
}
};

int main()
{
auto wild_castform = Castform();

std::cout << "Wild Castform appeared!\n";
std::cout << "Dex number " << wild_castform.dex_num() << '\n';
std::cout << "It's a " << wild_castform.type() << " type\n";

for(int i=0; i < 5; ++i) {
std::cout << "Catch attempt resulted in " << wild_castform.attempt_catch() << '\n';
}

return 0;
}


• It looks like all the Pokemon member variables should be private, not public.

• The Pokemon constructor takes catch_rate as an int, where it should be a float.

• The Pokemon constructor could std::move the string argument into m_type.

• Pokemon::type() could return by const& to avoid an unnecessary copy.

• Castform::m_forms is not used anywhere, but should probably also be static and const.

• When overriding a virtual function, we should always use the override keyword (and arguably also the virtual keyword):

virtual bool attempt_catch() override { ... }

• Use the C++11 <random> functionality, not rand().

Run-time polymorphism with virtual functions in C++ is driven by a need to treat objects of different types with the same interface. Unfortunately, this example lacks the motivation for it:

• Currently the attempt_catch() function could be implemented in the Pokemon base-class with no problem.

• There is no example of differing behavior (i.e. there should be a second pokemon type implementing a different attempt_catch() function). Maybe an attack function would work better?

• There is no demonstration of using the different types through the same interface. In C++ this usually boils down to storing different types in the same container (e.g. iterating a std::vector<std::unique_ptr<Pokemon>> and calling the virtual function). However, it might be simpler to pass two different pokemon types to a function taking a Pokemon reference:

void throw_pokeball(Pokemon const& target) { target.attempt_catch() } // or something


Depending on what this is actually for, I'd suggest approaching things in a "problem -> solution" way, both in terms of what the code does (see above), but also in terms of language development and why these features exist. i.e.

• "Here's what programmers used to have to do without this language feature [...]. It sucks because [...]"

• "This language feature allows us to do [...] safely and easily because [...]".

Note that there are many different types of both static and dynamic polymorphism in C++ (e.g. function overloading, implicit conversions, function objects, template parameters (traits, tags, etc.)), not just inheritance and virtual functions.

• Using std::move on the string argument into m_type in the Pokemon ctor would avoid another unnecessary string copy correct? – greg Jun 3 '19 at 18:37