How do I use derived classes if I only have a base class pointer? - c++

So here's what I got in a nutshell.
I have a base item class from which, potions, equipment, spells, etc.. are derived and several classes are derived from those and so on. Note: some derived classes have non-virtual class-specific member functions / data types.
I have also created a "random" armor/weapon generator.
What I want to have is an inventory kind of like this:
struct Hero_Inventory
{
std::vector<Spell*> Spell_Inventory;
std::vector<Potion*> Potion_Inventory;
std::vector<Equipment*> Equipment_Inventory;
Hero_Inventory() {}
};
Creating a container (inventory) for my spells and potions has been pretty straight forward. As they will be predefined. Using polymorphism and pointers wont be a problem
My main problem is figuring out to store and use (ex. access the weapon-class's specific member functions) my randomly generated weapons / armor (which are both derived from Equipment).
I would like for all of my "Equipment" to be in one container.
I'm generating all of my Equipment in a few functions so when I finish the generation process and end up with something like this:
Equipment * TestArmor = new Armor(/* Bunch of parameters go here */);
I don't know what to do with it, because as soon as that function goes out of scope I loose that pointer. And without pointers / referencing I can't use polymorphism, which is allowing me to keep my Equipment all in one container.
I'm really lost at this point and I'm looking for any suggestions or alternatives people can suggest. If you need more code I'll post it, just tell me what part(s) your interested in.
Sorry if I've been vague, this is my fist post. I'm usually pretty good at figuring things out on my own but this thing has me beat. If anyone needs more information ask and I'll try to provide it.
Thanks in advance,
-Ryan

Create a uniform interface for manipulating the Equipment objects:
class Equipment {
public:
virtual void render(Renderer& renderer) = 0;
virtual void createController(ControllerManager& controllerManager) = 0;
virtual void load(std::istream& input) = 0;
virtual void save(std::ostream& output) = 0;
};
The function createController is interesting as the equipment will be able to tell the ControllerManager how to create something that will manipulate its exact values.
If you want a function which allows interaction with other Equipment objects, you probably need the Visitor Pattern. This is a way of introducing polymorphism based on multiple types rather than a single type.

Related

Determine real type of base pointer in a big hierarchy without dynamic_cast

Suppose, that I have an abstract base State class and at least two derived classes AnimalState and PlantState(also abstract). Also, I have many derived classes from AnimalState and PlantState.
class State{} // abstract
class AnimalState: public State{} // abstract
class PlantState: public State{} // abstract
//maybe few more of such classes here
class AnimalStateSpecific1: public AnimalState{}
class AnimalStateSpecific2: public AnimalState{}
... //many of them
class PlantStateSpecific1: public PlantState{}
class PlantStateSpecific2: public PlantState{}
... //many of them
Now suppose, that I use them in some kind of method that operates on base State pointers. Those pointers are replaced over time with other pointers to different class from the State hierarchy. It happens by some rule, specifically within the predefined state graph.
Now to the question part. In order to determine the next state, I need to know the previous one. But since I have only base State pointers, I can not efficiently tell what type of state I have, without doing dynamic_cast to every derived class in the hierarchy that is not good. I can have some enum with all kinds of states that I have, but I do not really like that because I do not want to mix information from two hierarchy branches, as it is really different. Also, I do not like different enums for every branch in the hierarchy such as AnimalStateEnum, PlantStateEnum etc.
What is the best solution for this problem? Maybe my design is not good from the start? I want to keep it as generic as possible and work only with base class objects, if possible.
Now to the question part. In order to determine the next state, I need to know the previous one.
Simplest solution based on limited information we have - object, which knows it's own state creates next state object:
class State{
public:
...
virtual std::unique_ptr<State> transform( some data ) = 0;
};
then you implement it in each derived from State class which can change it's state and knows where it can move to. What data you need to pass is not a simple question - it depends on your task and may have various options, but you need to define something that can be used by all derived classes, as signature is defined on the base class and shared on all derived ones.
What is the best solution for this problem? Maybe my design is not good from the start?
This question is not trivial and only can be answered having pretty deep knowledge on your task. If you are unsure - implement a prototype and check if solution fits your problem well. Unfortunately the only way to learn how to create a good design is your own experience (except trivial cases of course).
You could simply have a virtual method next() inside the state class hierarchy,
and then do something similar to the following example:
State *globalState = nullptr;
void foo(State *s)
{
globalState = s->next();
}
Where each derived class will implement next() to its own meaning:
PlantStateSpecific1 *AnimalStateSpecific1::next(){ return new PlantStateSpecific1; }
AnimalStateSpecific1 *PlantStateSpecific1::next(){ return new AnimalStateSpecific1; }
This is more OOP than having an enum / integer descriptor of the derived class.
What you can have is an integer inside the base state class that every class below it will set in its constructor. Then you can either use a sereis of constants, a list of possible states with the id corresponding to the state type index, or use an enumerator.
The id is more flexible as you can create state types with relative ease and add handling to them without too much difficulty, aswell as if you want to create a new state from the id type.
Just one of the ways iv done this before, but there are probably many others.

C++ classes hierarchy design choice

In my simulation I have different objects that can be sensed in three ways: object can be seen and/or heard and/or smelled. For example, Animal can be seen, heard and smelled. And piece of Meat on the ground can be seen and smelled but not heard and Wall can only be seen. Then I have different sensors that gather this information - EyeSensor, EarSensor, NoseSensor.
Before state: brief version gist.github.com link
Before I started implementing NoseSensor I had all three functionality in one class that every object inherited - CanBeSensed because although classes were different they all needed the same getDistanceMethod() and if object implemented any CanBeSensed functionality it needed a senseMask - flags if object can be heard/seen/smelled and I didn't want to use virtual inheritance. I sacrificed having data members inside this class for smell, sounds, EyeInfo because objects that can only be seen do not need smell/sound info.
Objects then were registered in corresponding Sensor.
Now I've noticed that Smell and Sound sensors are the same and only differ in a single line inside a loop - one calls float getSound() and another float getSmell() on a CanBeSensed* object. When I create one of this two sensors I know what it needs to call, but I don't know how to choose that line without a condition and it's inside a tight loop and a virtual function.
So I've decided to make a single base class for these 3 functionality using virtual inheritance for base class with getDistanceMethod().
But now I had to make my SensorBase class a template class because of this method
virtual void sense(std::unordered_map<IdInt, CanBeSensed*>& objectsToSense) = 0;
, and it meant that I need to make SensorySubSystem class(manages sensors and objects in range) a template as well. And it meant that all my SubSystems like VisionSubSystem, HearingSubSystem and SmellSubSystem inherit from a template class, and it broke my SensorySystem class which was managing all SensorySubSystems through a vector of pointers to SensorySubSystem class std::vector<SensorySubSystem*> subSystems;
Please, could you suggest some solution for how to restructure this or how to make compiler decide at compile time(or at least decide once per call//once per object creation) what method to call inside Hearing/Smell Sensors.
Looking at your original design I have a few comments:
The class design in hierarchy.cpp looks quite ok to me.
Unless distance is something specific to sensory information getDistance() doesn't look like a method that belongs into this class. It could be moved either into a Vec2d-class or to a helper function (calculatePositon(vec2d, vec2d)). I do not see, why getDistance() is virtual, if it does something different than calculating the distance between the given position and the objects position, then it should be renamed.
The class CanBeSensed sounds more like a property and should probably be renamed to e.g. SensableObject.
Regarding your new approach:
Inheritance should primarily be used to express concepts (is-a-relations), not to share code. If you want to reuse an algorithm, consider writing an algorithm class or function (favour composition over inheritance).
In summary I propose to keep your original class design cleaning it up a little as described above. You could add virtual functions canBeSmelled/canBeHeard/canBeSeen to CanBeSensed.
Alternatively you could create a class hierachy:
class Object{ getPosition(); }
class ObjectWithSmell : virtual Object
class ObjectWithSound : virtual Object
...
But then you'd have to deal with virtual inheritance without any noticeable benefit.
The shared calculation code could go into an algorithmic class or function.

Accessing subclass functions of member of collection of parent class objects

(Refer Update #1 for a concise version of the question.)
We have an (abstract) class named Games that has subclasses, say BasketBall and Hockey (and probably many more to come later).
Another class GameSchedule, must contain a collection GamesCollection of various Games objects. The issue is that we would, at times, like to iterate only through the BasketBall objects of GamesCollection and call functions that are specific to it (and not mentioned in the Games class).
That is, GameSchedule deals with a number of objects that broadly belong to Games class, in the sense that they do have common functions that are being accessed; at the same time, there is more granularity at which they are to be handled.
We would like to come up with a design that avoids unsafe downcasting, and is extensible in the sense that creating many subclasses under Games or any of its existing subclasses must not necessitate the addition of too much code to handle this requirement.
Examples:
A clumsy solution that I came up with, that doesn't do any downcasting at all, is to have dummy functions in the Game class for every subclass specific function that has to be called from GameSchedule. These dummy functions will have an overriding implementation in the appropriate subclasses which actually require its implementation.
We could explicitly maintain different containers for various subclasses of Games instead of a single container. But this would require a lot of extra code in GameSchedule, when the number of subclasses grow. Especially if we need to iterate through all the Games objects.
Is there a neat way of doing this?
Note: the code is written in C++
Update# 1: I realized that the question can be put in a much simpler way. Is it possible to have a container class for any object belonging to a hierarchy of classes? Moreover, this container class must have the ability to pick elements belonging to (or derive from) a particular class from the hierarchy and return an appropriate list.
In the context of the above problem, the container class must have functions like GetCricketGames, GetTestCricketGames, GetBaseballGame etc.,
This is exactly one of the problems that The "Tell, Don't Ask" principle was created for.
You're describing an object that holds onto references to other objects, and wants to ask them what type of object they are before telling them what they need to do. From the article linked above:
The problem is that, as the caller, you should not be making decisions based on the state of the called object that result in you then changing the state of the object. The logic you are implementing is probably the called object’s responsibility, not yours. For you to make decisions outside the object violates its encapsulation.
If you break the rules of encapsulation, you not only introduce the runtime risks incurred by rampant downcasts, but also make your system significantly less maintainable by making it easier for components to become tightly coupled.
Now that that's out there, let's look at how the "Tell, Don't Ask" could be applied to your design problem.
Let's go through your stated constraints (in no particular order):
GameSchedule needs to iterate over all games, performing general operations
GameSchedule needs to iterate over a subset of all games (e.g., Basketball), to perform type-specific operations
No downcasts
Must easily accommodate new Game subclasses
The first step to following the "Tell, Don't Ask" principle is identifying the actions that will take place in the system. This lets us take a step back and evaluate what the system should be doing, without getting bogged down into the details of how it should be doing it.
You made the following comment in #MarkB's answer:
If there's a TestCricket class inheriting from Cricket, and it has many specific attributes concerning the timings of the various innings of the match, and we would like to initialize the values of all TestCricket objects' timing attributes to some preset value, I need a loop that picks all TestCricket objects and calls some function like setInningTimings(int inning_index, Time_Object t)
In this case, the action is: "Initialize the inning timings of all TestCricket games to a preset value."
This is problematic, because the code that wants to perform this initialization is unable to differentiate between TestCricket games, and other games (e.g., Basketball). But maybe it doesn't need to...
Most games have some element of time: Basketball games have time-limited periods, while Baseball games have (basically) innings with basically unlimited time. Each type of game could have its own completely unique configuration. This is not something we want to offload onto a single class.
Instead of asking each game what type of Game it is, and then telling it how to initialize, consider how things would work if the GameSchedule simply told each Game object to initialize. This delegates the responsibility of the initialization to the subclass of Game - the class with literally the most knowledge of what type of game it is.
This can feel really weird at first, because the GameSchedule object is relinquishing control to another object. This is an example of the Hollywood Principle. It's a completely different way of solving problems than the approach most developers initially learn.
This approach deals with the constraints in the following ways:
GameSchedule can iterate over a list of Games without any problem
GameSchedule no longer needs to know the subtypes of its Games
No downcasting is necessary, because the subclasses themselves are handling the subclass-specific logic
When a new subclass is added, no logic needs to be changed anywhere - the subclass itself implements the necessary details (e.g., an InitializeTiming() method).
Edit: Here's an example, as a proof-of-concept.
struct Game
{
std::string m_name;
Game(std::string name)
: m_name(name)
{
}
virtual void Start() = 0;
virtual void InitializeTiming() = 0;
};
// A class to demonstrate a collaborating object
struct PeriodLengthProvider
{
int GetPeriodLength();
}
struct Basketball : Game
{
int m_period_length;
PeriodLengthProvider* m_period_length_provider;
Basketball(PeriodLengthProvider* period_length_provider)
: Game("Basketball")
, m_period_length_provider(period_length_provider)
{
}
void Start() override;
void InitializeTiming() override
{
m_period_length = m_time_provider->GetPeriodLength();
}
};
struct Baseball : Game
{
int m_number_of_innings;
Baseball() : Game("Baseball") { }
void Start() override;
void InitializeTiming() override
{
m_number_of_innings = 9;
}
}
struct GameSchedule
{
std::vector<Game*> m_games;
GameSchedule(std::vector<Game*> games)
: m_games(games)
{
}
void StartGames()
{
for(auto& game : m_games)
{
game->InitializeTiming();
game->Start();
}
}
};
You've already identified the first two options that came to my mind: Make the base class have the methods in question, or maintain separate containers for each game type.
The fact that you don't feel these are appropriate leads me to believe that the "abstract" interface you provide in the Game base class may be far too concrete. I suspect that what you need to do is step back and look at the base interface.
You haven't given any concrete example to help, so I'm going to make one up. Let's say your basketball class has a NextQuarter method and hockey has NextPeriod. Instead, add to the base class a NextGameSegment method, or something that abstracts away the game-specific details. All the game-specific implementation details should be hidden in the child class with only a game-general interface needed by the schedule class.
C# supports reflections and by using the "is" keyword or GetType() member function you could do these easily. If you are writing your code in unmanaged C++, I think the best way to do this is add a GetType() method in your base class (Games?). Which in its turn would return an enum, containing all the classes that derive from it (so you would have to create an enum too) for that. That way you can safely determine the type you are dealing with only through the base type. Below is an example:
enum class GameTypes { Game, Basketball, Football, Hockey };
class Game
{
public:
virtual GameTypes GetType() { return GameTypes::Game; }
}
class BasketBall : public Game
{
public:
GameTypes GetType() { return GameTypes::Basketball; }
}
and you do this for the remaining games (e.g. Football, Hockey). Then you keep a container of Game objects only. As you get the Game object, you call its GetType() method and effectively determine its type.
You're trying to have it all, and you can't do that. :) Either you need to do a downcast, or you'll need to utilize something like the visitor pattern that would then require you to do work every time you create a new implementation of Game. Or you can fundamentally redesign things to eliminate the need to pick the individual Basketballs out of a collection of Games.
And FWIW: downcasting may be ugly, but it's not unsafe as long as you use pointers and check for null:
for(Game* game : allGames)
{
Basketball* bball = dynamic_cast<Basketball*>(game);
if(bball != nullptr)
bball->SetupCourt();
}
I'd use the strategy pattern here.
Each game type has its own scheduling strategy which derives from the common strategy used by your game schedule class and decouples the dependency between the specific game and game schedule.

Retrieving values of collection from multiple classes, what's the correct way?

Before anything, thanks for reading!
I'm developing an application in C++ and I want an advice about a design issue. Let me explain:
The main class of my application has some collections, but other classes eventually need to get a value from one of those collections. Something like this:
class MainClass {
private:
// Collections are internally implemented as QHash
Collection<Type1> col1;
Collection<Type2> col2;
};
class RosterUnit {
public:
RosterUnit() {
/* This method needs to get a specific value from col1 and
initialize this class with that data */
}
};
class ObjectAction {
public:
virtual void doAction() = 0;
};
class Action1 : public ObjectAction {
public:
void doAction() {
// This needs a specific value from col2
}
};
class Action2 : public ObjectAction {
public:
void doAction() {
// This needs a specific value from col1
}
};
My first approach was passing the whole collection as parameter when needed, but it is not so good for ObjectAction subclasses, because I would have to pass the two collections and if I later create another subclass of ObjectAction and it needs to get an element from other collection (suppose col3), I would have to modify the doAction() signature of every ObjectAction subclass, and I think that is not too flexible. Also, suppose I have a Dialog and want to create a RosterUnit from there. I would have to pass the collection to the dialog just to create the RosterUnit.
Next I decided to use static variables in RosterUnit and ObjectAction that pointed to the collections, but I'm not very happy with that solution. I think it is not flexible enough.
I have been reading about design patterns and I first thought a Singleton with get functions could be a good choice, but after some more investigation I think it isn't a proper design for my case. It would be easier and more or less the same if I use global variables, which don't seem to be the right way.
So, could you give some advices, please?
Thank you very much!
As mentioned previously, Iterators are good for abstracting away the details of the Collection. But going this route implies that the objects that use the Iterators will need to know about what's inside the Collection. Meaning they will need to know how to decide which object in the Collection they need, thus increasing the coupling. (more details below in the Factory paragraph) This is something you need to consider.
Another approach would be to create accessor methods on the MainClass that take some sort of key and return an object from the Collection (findObject(key)). Internally the MainClass methods would search through the container(s) and return the appropriate object. To use this approach, you will however need access to the MainClass, either by dependancy injection as mentioned before, or possibly making it a Singleton (not recomended in this scenario, though).
With the info provided so far, it may even be better for your ObjectAction Factory to have a reference to the MainClass, and as a part of the ObjectAction creation logic, call the appropriate MainClass accessor and pass the result into the ObjectAction, thus decoupling the ObjectAction Objects from the MainClass.
You probably want to use iterators, they exist exactly for the purpose of abstracting away sequences from specific containers.
If your issue is how to pass the iterators to the code that needs them in the first place, do not give in to the temptation to use globals. It may look more convoluted if you have to pass parameters in, but your code is that much more decoupled for it. "Dependency Injection" is a good keyword if you want to read more about this topic.
I would also advise you to check out std::function or boost::function instead of inheriting from ObjectAction. Functional style is getting more common in modern C++, as opposed to how it's usually done in languages like Java.
There's not enough information here of what you are trying to do. You make it sound like 'at some point in the future, this statically created action needs this data that was left behind.' How does that make any sense? I would say either construct the actions with the data, as you would for instance with a Future or Callable), or have the command ask for the next piece of data, in which case you are just implementing a Work queue.
Sounds like you are trying to do something like a thread pool. If these actions are in any way related, then you should have then in some composing object, implementing something like the Template Method pattern, e.g. execute() is abstract and calls a few other methods in a fixed sequence and that cannot be overridden, the other methods must be (protocol enforcement).

Can someone explain the benefits of polymorphism?

So I understand pretty much how it works, but I just can't grasp what makes it useful. You still have to define all the separate functions, you still have to create an instance of each object, so why not just call the function from that object vs creating the object, creating a pointer to the parent object and passing the derived objects reference, just to call a function? I don't understand the benefits of taking this extra step.
Why do this:
class Parent
{
virtual void function(){};
};
class Derived : public Parent
{
void function()
{
cout << "derived";
}
};
int main()
{
Derived foo;
Parent* bar = &foo;
bar->function();
return -3234324;
}
vs this:
class Parent
{
virtual void function(){};
};
class Derived : public Parent
{
void function()
{
cout << "derived";
}
};
int main()
{
Derived foo;
foo.function();
return -3234324;
}
They do exactly the same thing right? Only one uses more memory and more confusion as far as I can tell.
Both your examples do the same thing but in different ways.
The first example calls function() by using Static binding while the second calls it using Dynamic Binding.
In first case the compiler precisely knows which function to call at compilation time itself, while in second case the decision as to which function should be called is made at run-time depending on the type of object which is pointed by the Base class pointer.
What is the advantage?
The advantage is more generic and loosely coupled code.
Imagine a class hierarchy as follows:
The calling code which uses these classes, will be like:
Shape *basep[] = { &line_obj, &tri_obj,
&rect_obj, &cir_obj};
for (i = 0; i < NO_PICTURES; i++)
basep[i] -> Draw ();
Where, line_obj, tri_obj etc are objects of the concrete Shape classes Line, Triangle and so on, and they are stored in a array of pointers of the type of more generalized base class Shape.
This gives the additional flexibility and loose coupling that if you need to add another concrete shape class say Rhombus, the calling code does not have to change much, because it refers to all concrete shapes with a pointer to Base class Shape. You only have to make the Base class pointer point to the new concrete class.
At the sametime the calling code can call appropriate methods of those classes because the Draw() method would be virtual in these classes and the method to call will be decided at run-time depending on what object the base class pointer points to.
The above is an good example of applying Open Closed Principle of the famous SOLID design principles.
Say you want someone to show up for work. You don't know whether they need to take a car, take a bus, walk, or what. You just want them to show up for work. With polymorphism, you just tell them to show up for work and they do. Without polymorphism, you have to figure out how they need to get to work and direct them to that process.
Now say some people start taking a Segway to work. Without polymorphism, every piece of code that tells someone to come to work has to learn this new way to get to work and how to figure out who gets to work that way and how to tell them to do it. With polymorphism, you put that code in one place, in the implementation of the Segway-rider, and all the code that tells people to go to work tells Segway-riders to take their Segways, even though it has no idea that this is what it's doing.
There are many real-world programming analogies. Say you need to tell someone that there's a problem they need to investigate. Their preferred contact mechanism might be email, or it might be an instant message. Maybe it's an SMS message. With a polymorphic notification method, you can add a new notification mechanism without having to change every bit of code that might ever need to use it.
polymorphism is great if you have a list/array of object which share a common ancestor and you wich to do some common thing with them, or you have an overridden method. The example I learnt the concept from, use shapes as and overriding the draw method. They all do different things, but they're all a 'shape' and can all be drawn. Your example doesn't really do anything useful to warrant using polymorphism
A good example of useful polymorphism is the .NET Stream class. It has many implementations such as "FileStream", "MemoryStream", "GZipStream", etcetera. An algorithm that uses "Stream" instead of "FileStream" can be reused on any of the other stream types with little or no modification.
There are countless examples of nice uses of polymorphism. Consider as an example a class that represents GUI widgets. The most base classs would have something like:
class BaseWidget
{
...
virtual void draw() = 0;
...
};
That is a pure virtual function. It means that ALL the class that inherit the Base will need to implement it. And ofcourse all widgets in a GUI need to draw themselves, right? So that's why you would need a base class with all of the functions that are common for all GUI widgets to be defined as pure virtuals because then in any child you will do like that:
class ChildWidget
{
...
void draw()
{
//draw this widget using the knowledge provided by this child class
}
};
class ChildWidget2
{
...
void draw()
{
//draw this widget using the knowledge provided by this child class
}
};
Then in your code you need not care about checking what kind of widget it is that you are drawing. The responsibility of knowing how to draw itself lies with the widget (the object) and not with you. So you can do something like that in your main loop:
for(int i = 0; i < numberOfWidgets; i++)
{
widgetsArray[i].draw();
}
And the above would draw all the widgets no matter if they are of ChildWidget1, ChildWidget2, TextBox, Button type.
Hope that it helps to understand the benefits of polymorphism a bit.
Reuse, generalisation and extensibility.
I may have an abstract class hierarchy like this: Vehicle > Car. I can then simply derive from Car to implement concrete types SaloonCar, CoupeCar etc. I implement common code in the abstract base classes. I may have also built some other code that is coupled with Car. My SaloonCar and CoupeCar are both Cars so I can pass them to this client code without alteration.
Now consider that I may have an interface; IInternalCombustionEngine and a class coupled with with this, say Garage (contrived I know, stay with me). I can implement this interface on classes defined in separate class hierarchies. E.G.
public abstract class Vehicle {..}
public abstract class Bus : Vehicle, IPassengerVehicle, IHydrogenPowerSource, IElectricMotor {..}
public abstract class Car : Vehicle {..}
public class FordCortina : Car, IInternalCombustionEngine, IPassengerVehicle {..}
public class FormulaOneCar : Car, IInternalCombustionEngine {..}
public abstract class PowerTool {..}
public class ChainSaw : PowerTool, IInternalCombustionEngine {..}
public class DomesticDrill : PowerTool, IElectricMotor {..}
So, I can now state that an object instance of FordCortina is a Vehicle, it's a Car, it's an IInternalCombustionEngine (ok contrived again, but you get the point) and it's also a passenger vehicle. This is a powerful construct.
The poly in polymorphic means more than one. In other words, polymorphism is not relevant unless there is more than one derived function.
In this example, I have two derived functions. One of them is selected based on the mode variable. Notice that the agnostic_function() doesn't know which one was selected. Nevertheless, it calls the correct version of function().
So the point of polymorphism is that most of your code doesn't need to know which derived class is being used. The specific selection of which class to instantiate can be localized to a single point in the code. This makes the code much cleaner and easier to develop and maintain.
#include <iostream>
using namespace std;
class Parent
{
public:
virtual void function() const {};
};
class Derived1 : public Parent
{
void function() const { cout << "derived1"; }
};
class Derived2 : public Parent
{
void function() const { cout << "derived2"; }
};
void agnostic_function( Parent const & bar )
{
bar.function();
}
int main()
{
int mode = 1;
agnostic_function
(
(mode==1)
? static_cast<Parent const &>(Derived1())
: static_cast<Parent const &>(Derived2())
);
}
Polymorphism is One of the principles OOP. With polymorphism you can choose several behavior in runtime. In your sample, you have a implementation of Parent, if you have more implementation, you can choose one by parameters in runtime. polymorphism help for decoupling layers of application. in your sample of third part use this structers then it see Parent interface only and don't know implementation in runtime so third party independ of implementations of Parent interface. You can see Dependency Injection pattern also for better desing.
Just one more point to add. Polymorphism is required to implement run-time plug-ins. It is possible to add functionality to a program at run-time. In C++, the derived classes can be implemented as shared object libraries. The run time system can be programmed to look at a library directory, and if a new shared object appears, it links it in and can start to call it. This can also be done in Python.
Let's say that my School class has a educate() method. This method accepts only people who can learn. They have different styles of learning. Someone grasps, someone just mugs it up, etc.
Now lets say I have boys, girls, dogs, and cats around the School class. If School wants to educate them, I would have to write different methods for the different objects, under School.
Instead, the different people Objects (boys,girls , cats..) implement the Ilearnable interface. Then, the School class does not have to worry about what it has to educate.
School will just have to write a
public void Educate (ILearnable anyone)
method.
I have written cats and dogs because they might want to visit different type of school. As long as it is certain type of school (PetSchool : School) and they can Learn, they can be educated.
So it saves multiple methods that have the same implementation but different input types
The implementation matches the real life scenes and so it's easy for design purposes
We can concentrate on part of the class and ignore everything else.
Extension of the class (e.g. After years of education you come to know, hey, all those people around the School must go through GoGreen program where everyone must plant a tree in the same way. Here if you had a base class of all those people as abstract LivingBeings, we can add a method to call PlantTree and write code in PlantTree. Nobody needs to write code in their Class body as they inherit from the LivingBeings class, and just typecasting them to PlantTree will make sure they can plant trees).