I am a beginner and tryed to find an answer on this website but I was not able to figure out how to solve my specific C++ OOP problem.
Short: I want to access and change values of a parent class from subclass instances, but somehow my approach seems not to be working.
Example: There are many Car instances in my program (created with new construct). If one of the Car objects detects a collision, all Car instances should inverse their movement. The Car that registered the collision should call the parents' ChangeSpeed method or change the speed value directly.
Problem: the speed variable seems not to be updated. Is there something wrong with this particular code/ approach or do I have to search for my problem somewhere else?
// SpeedControl.h ------------------------------
class SpeedControl
{
public:
void ChangeSpeed(int);
protected:
int speed;
};
class Car:
public SpeedControl
{
public:
void MoveCar();
void DetectCollision();
private:
int position;
};
// SpeedControl.cpp ------------------------------
#include SpeedControl.h
SpeedControl::SpeedControl(void)
{
speed = 10;
}
SpeedControl::~SpeedControl(void)
{
}
SpeedControl::ChangeSpeed(int _value)
{
speed *= _value;
}
// Car.cpp ------------------------------
#include SpeedControl.h
Car::Car(void)
{
position = 100;
}
Car::~Car(void)
{
}
Car::MoveCar()
{
position += speed; // speed should be accessible?
}
Car::DetectCollision()
{
speed *= (-1); // inverse speed variable in parent class to inverse direction of ALL cars
// alternative:
// ChangeSpeed(-1); // call parent function to inverse speed
}
This looks like a problem where the observer pattern is the right solution.
You should implement a GetSpeed() in your SpeedControl class, which returns the current speed.
Then you can use this in MoveCar function:
ChangeSpeed(GetSpeed() + GetSpeed()); // Assuming you want to double the speed.
and in your collision:
ChangeSpeed(-GetSpeed());
Alternatively, you could make "ChangeSpeed" a multiplication rather than an addition.
You didn't state what exactly is wrong with your code, but from glancing on it, you're using private inheritance, which hides all parent's members from derived classes.
class Child : public Parent { };
The line above will ensure that the Parent members are accessible from Child.
You seem to misunderstand inheritance. What you need is a static variable.
Define static int speed in Car class. You can drop SpeedControl class.
Related
I don't understand what is the point of having a function inside an object if you can even modify data outside the object for example (I'm using struct for this example):
int lamborghini_horsepower1 = 350;
struct car {
string model;
string color;
int horsepower;
void check(int horsepower) {
if (horsepower > 349) {
cout << "this car has many horsepowers";
}
}
};
car ford;
ford.check(lamborghini_horsepower1);
in this case it would run anyways.
it would make sense if the function could only operate inside data of the object because as it say they are the data of the object and why can the function access to others variables? for example what if you pass another variable in this case lamborghini_horsepower is not part of the the object ford. and still can be cecked by the ford function even if they are different veichle.
are for class different?
In structs, functions don't have too much of an impact because data can be modified from the outside. However, they still can act as a convenience feature, especially when properly written. Your function takes horsepower as an argument, which is unnecessary because horsepower is already a field in the struct. If you change your function to:
void check() {
if (horsepower > 349) {
cout << "this car has many horsepowers" << endl;
}
}
you can call it with ford.check() and it'll automatically retrieve the horsepower from the ford variable. In classes, fields can be declared as private, which means that they can't be accessed from the outside and must be modified purely with functions defined inside the class.
are for class different?
Classes are not accessible from the outside by default, so if you did
class car{
string model;
string color;
int horsepower;
void check(int horsepower) {
if(horsepower>349)
{
cout << "this car has many horsepowers";
}
}
};
Then nothing in that struct would be accessible from outside the class. But there is a way to modify the what variables and functions can be accessed from the outside with access modifiers.
The purpose of making functions and variables inaccessible outside the object is to protect them from being unintentionally called or altered
The short answer is that your example wouldn't be very efficient for objects. I would just keep the function outside the struct in that example.
The purpose of classes and structs is to put variables and functions into one package. The example you have doesn't require an object. The basis behind object design is to mimic real world objects by giving them abilities(functions) and properties (variables).
The check() function here isn't an ability we normally find in cars. Instead, a car has certain properties like color, speed, and direction. A car also has abilities like accelerate, reverse, turn left and turn right. With this we can create a car object with these properties (variables) and abilities (functions)
struct Car
{
int speed;
std::string color;
std::string direction;
Car() // As soon as the object is created, this function will be called and set speed to 0.
{
speed = 0;
}
void speedUp()
{
speed += 5;
}
void slowDown()
{
speed -= 5;
}
void stop()
{
speed = 0;
}
void reverse()
{
stop() // This will stop the car first
speed -= 2; // Move the car backwords
}
void turnLeft()
{
direction = "left";
}
void turnRight()
{
direction = "right";
}
};
So now you can create different objects of the same class\struct with different speeds, direction, and color.
I have a use case that involves collections of sensor objects that return a bool (indicating the state of the sensor). In some cases the collection object is interested in the inverse of a the sensor value, but I want to use the same interface for both cases so that the collection doesn't need to track this. An example might be
Result = sensorA | not(sensorB)
where the the value of sensorA and not(sensorB) are accessed using the same interface. I've come up with a couple of solutions for this, none of which seem as simple as I originally expected the problem to be.
Firstly, I can realize the goal by creating another class that inherits from the same base interface and performs the translation. However this seems a little clunky as I have to instantiate a inverting object for each sensor:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
class ObservedSensorBase
{
public:
virtual bool getState(void) = 0;
protected:
ObservedSensorBase() { inverted = new InvertSensor(this); }
};
class ConcreteSensor : public ObservedSensorBase
{
public:
ConcreteSensor(bool state) :mState(state) {}
bool getState(void) { return mState; }
private:
bool mState;
};
class InvertSensor : public ObservedSensorBase
{
public:
InvertSensor(ObservedSensorBase *sensor) :mSensor(sensor) {}
bool getState(void) { return !mSensor->getState(); }
private:
ObservedSensorBase *mSensor;
};
int main()
{
ConcreteSensor sensorA(true);
InvertSensor notSensorA(&sensorA);
vector <class ObservedSensorBas*> sensors;
sensors.push_back(&sensorA);
sensors.push_back(¬SensorA);
for (class ObservedSensorBase* it : sensors)
{
cout << it->getState() << endl;
}
return 0;
}
Prints:
1
0
Ideally I'm looking for the original concrete sensor class to be able to return the inverted functionality. I can do this if I add a public class to each concrete sensor:
class ConcreteSensor : public ObservedSensorBase
{
public:
ConcreteSensor(bool state) :mState(state),inv(this) {}
bool getState(void) { return mState; }
class InvertSensor inv;
private:
bool mState;
};
...
sensors.push_back(&sensorA.inv);
Prints
0
but this seems a little cumbersome, as its a new variable in each concrete class. I can't add it to the base class, as InvertSensor inherits from the base, so InvertSensor isn't fully defined and can't be instantiated (at least I haven't been able to do so).
The other approach I've investigated is using an object factory:
ObservedSensorBase *invertFactory(ObservedSensorBase *sensor)
{
static map<ObservedSensorBase *, ObservedSensorBase *> m;
// Create an instance of the inverter for this object if it doesn't already exist
if (m.find(sensor) == m.end())
{
m[sensor] = new InvertSensor(sensor);
}
// Provide the inverting object for the passed sensor
return m[sensor];
}
...
sensors.push_back(invertFactory(&sensorA));
Prints
0
Is there another solution that I'm missing? Ideally something inherent in the class that each concrete instance can inherit from, but at this point it's become a bit of an intellectual challenge as well :)
--- EDIT ---
Thanks for the comments so far.
To clarify the objective better, this is for a little project for an Arduino to control signals on a model railroad. For the purposes here, assume that the signals can only show green and red. They show red when any track occupancy circuit or switch orientation that the signal is 'protecting' against indicates its unsafe for a train to proceed (and green otherwise).
Both the track detection and switch orientation objects would be concrete instances of the base sensor, but it's the switch orientation that creates this use case. If we have two signals, each of which is 'protecting' the two approaches to the two-track end of a single switch, one signal will want to use the switch orientation sensor 'as-is', and the other will want to use the inverted sensor value (to represent which way the switch is thrown).
I'm wanting to be able to invert the sensors' state representation when loading the into the signal object that holds them to avoid having to store a separate 'invert this signal' indication in the signal object, or manually instantiate a separate object that performs the inversion.
So something like
Signal1 protects SensorA (trackA) and Switch B
Signal2 protects SensorC (trackC) and not(SwitchB)
Here is an example of the signal (a container of sensors that just ORs them all together) e.g.
class Signal
{
public:
void protect(class ObservedSensorBase *sensor) { mSensors.push_back(sensor); }
void periodicLoop(void)
{
bool anyProtectedSensorActive = false;
for ( auto it = mSensors.begin();
it != mSensors.end() && !anyProtectedSensorActive;
++it)
{ anyProtectedSensorActive |= (*it)->getState(); }
if(anyProtectedSensorActive)
{ /* set Signal Red */ }
else
{ /* set signal Green */ }
}
private:
vector <class ObservedSensorBase*> mSensors; // protected sensors
};
...
Signal signal1;
Signal signal2;
signal1.protect(&sensorA);
signal1.protect(&sensorB);
signal1.protect(&sensorC);
signal1.protect(¬SensorB);
However, after playing with #Jason C's recommendation to put something in the base class (which I couldn't get working prior to asking the question, or after his suggestion) it occured to me that I could create
// Invert Sensor and ObservedSensorBase are declared as above...
class InvertedSensorBase : public ObservedSensorBase
{
public:
InvertedSensorBase() : inverted(this) {}
class InvertSensor inverted;
};
// Change the inheritance of the concrete observer
//class ConcreteSensor : public ObservedSensorBase
class ConcreteSensor : public InvertedSensorBase
And now SensorA.inverted seems to fit the bill very well.
Of course, since this is mostly a side project to return to C++ and learn C++11 after a long absence, if anyone has alternate suggestions about any point, I'd be more than happy to see them.
If you want a really no-effort solution you could store pair<ObservedSensorBase*,bool>'s in your container, where the boolean is whether you want to invert or not, and just have your logic invert the value based on that bool:
typedef pair<ObservedSensorBase *,bool> SensorWithFlag; // ...or something
vector<SensorWithFlag> sensors;
sensors.push_back(SensorWithFlag(sensor1, true)); // invert
sensors.push_back(SensorWithFlag(sensor2, false)); // don't invert
// then later when you use it, say 'n' is an index:
bool state = (sensors[n].first->getState() != sensors[n].second);
But if not, I suppose you could do the inversion in the base:
class ObservedSensorBase {
...
public:
void setInvertState (bool invertState) {
invertState_ = invertState;
}
bool getState () {
return invertState_ != getState_(); // != is xor
}
protected:
virtual bool getState_ () = 0;
private:
bool invertState_;
};
Then all subclasses implement getState_ instead of getState, and all have the ability to have their results inverted by setting setInvertState(true).
But this seems weird. Perhaps you could add some more details about how your containers are using these values. I feel like there may be a better way in general to structure your program and algorithms.
Another option is to use your "inverting filter" option but manage it in the base:
class ObservedSensorBase {
...
public:
ObservedSensorBase (...) : inv_(this) { ... }
InvertSensor * inverted () { return &inv_; }
private:
InvertSensor inv_;
};
Then you can just add mySensor->inverted() to your container when needed. This has the following caveats:
Do not call any virtual methods of ObservedSensorBase from InvertSensor's constructor.
Do not call any methods of InvertSensor that may lead to virtual base methods being called, from ObservedSensorBase's constructor.
Pointer returned by inverted() is invalidated when sensor is deleted.
The first two points are important because this won't be fully constructed yet when constructing subclasses.
This way, every sensor automatically has an inverted version of itself that comes along with it, and you don't have to manage them manually.
Yet another solution is to create wrappers around sensor objects, but keep them simple and store them directly in containers instead of storing pointers to them, to keep memory management easier. For example:
class SensorValue {
public:
SensorValue (ObservedSensorBase *s, bool invert)
: s_(s), i_(invert) { }
bool getState () { return i_ != s_->getState(); }
ObservedSensorBase * sensor () { return s_; }
private:
ObservedSensorBase *s_;
bool i_;
};
// then later, let's say you have some sensors:
ObservedSensorBase *sensor1 = ...;
ObservedSensorBase *sensor2 = ...;
// you can have containers like this:
vector<SensorValue> collection1, collection2;
// and you can use normal/inverted states as needed:
collection1.push_back(SensorValue(sensor1, false)); // normal values
collection1.push_back(SensorValue(sensor2, false));
collection2.push_back(SensorValue(sensor1, true)); // and inverted
collection2.push_back(SensorValue(sensor2, true)); // at the same time
// if you ever need the sensor object itself you can use SensorValue#sensor:
for (vector<SensorValue>::iterator i = collection1.begin();
i != collection1.end(); ++ i)
{
bool state = i->getState(); // normal or inverted, transparent to us here
ObservedSensorBase *sensor = i->sensor(); // can be used for whatever.
// note that i->getState() != i->sensor()->getState() if we're
// using an inverted SensorValue.
}
// and they aren't pointers, you can just do this with no leaks:
collection1.clear();
collection2.clear();
// although of course you still do this for sensor cleanup:
delete sensor2;
delete sensor1;
This is sort of conceptually like your inverted sensor object approach except SensorValue isn't an ObservedSensorBase, it's lightweight and cheaply copyable, and you can just store them directly in containers instead of passing around pointers.
It's very similar to storing e.g. pair<ObservedSensorBase*,bool> (where you store sensor and invert flag) in your containers instead, except unlike pair it gives you a convenient getState() member, and has some semantic meaning.
I have a problem with typename SnakeGame. I would like to know how to make SnakeGame to global type in class KeyboardEvents. Now a nested class like DirectionKeyboard don't know what the type SnakeGame is, since it only sees see KeyboardEvents<SnakeGame> type. I don't know how to change it :P
Here's the error:
no know conversion for argument 1 from 'KeyboardEvents SnakeGame>&' to 'SnakeGame&'
I would really appreciate help .
keyboardEvents.hpp
#include<SFML/Graphics.hpp>
template <typename SnakeGame>
class KeyboardEvents {
public:
virtual ~KeyboardEvents() = default;
protected:
class DirectionKeyboardEvent{
public:
virtual ~DirectionKeyboardEvent() = default;
virtual void direction(SnakeGame&) = 0; // error no know conversion
};
class GoRight : public DirectionKeyboardEvent {
public:
void direction(SnakeGame& snakeObj) {
snakeObj.snake[0].xCoor+=1;
}
};
class GoRight : public DirectionKeyboardEvent {
public:
void direction(SnakeGame& snakeObj){
snakeObj.snake[0].xCoor += 1;
}
};
class GoLeft : public DirectionKeyboardEvent{
public:
void direction(SnakeGame& snakeObj){
snakeObj.snake[0].xCoor-=1;
}
};
class GoUp:public DirectionKeyboardEvent{
public:
void direction(SnakeGame& snakeObj){
snakeObj.snake[0].yCoor-=1;
}
};
class GoDown : public DirectionKeyboardEvent{
public:
void direction(SnakeGame& snakeObj){
snakeObj.snake[0].yCoor+=1;
}
};
std::map<sf::Keyboard::Key, std::shared_ptr<DirectionKeyboardEvent>> mapOfDirects;
void initializeDirectionMap() {
mapOfDirects[sf::Keyboard::Right] = std::shared_ptr< DirectionKeyboardEvent >(new GoRight);
mapOfDirects[sf::Keyboard::Left] = std::shared_ptr<DirectionKeyboardEvent>(new GoLeft);
mapOfDirects[sf::Keyboard::Up] = std::shared_ptr<DirectionKeyboardEvent>(new GoUp);
mapOfDirects[sf::Keyboard::Down] = std::shared_ptr<DirectionKeyboardEvent>(new GoDown);
}
void chooseMethodFromKeyboardArrows(sf::Keyboard::Key codeFromKeyboard) {
auto iterator = mapOfDirects.find(codeFromKeyboard);
if(iterator!=mapOfDirects.end()){
iterator->second->direction(*this);//left , right,up , down, pause
mainDirection=codeFromKeyboard;
} else {
mapOfDirects[mainDirection]->direction(*this);
}
}
};
Here's the class where I use KeyboardEvents ~ snakeGame.hpp
#include"keyboardEvents.hpp"
class SnakeGame:public Screen, public KeyboardEvents<SnakeGame> {
public:
SnakeGame(int size=16, int width=15, int height=15, int timeDelay=60000)
: Screen(size, width, height), KeyboardEvents<SnakeGame>(), timeDelay(timeDelay) {}
};
In your try to call the DirectionKeyboardEvent::direction inside the KeyboardEvents class.
Even if you put a template parameter that happens to be the child class, there is no means to compiler can know in advance that KeyboardEvents<SnakeGame> will absolutely be extended by the class SnakeGame.
I mean, one could write this code:
KeyboardEvents<SnakeGame> keyboardEvents;
keyboardEvents.chooseMethodFromKeyboardArrows(/* some key */);
In that case, keyboardEvents is not related that much to SnakeGame. In fact there is no SnakeGame instance created at all! The compiler is right, the function chooseMethodFromKeyboardArrows that call direction is wrong to assume that a KeyboardEvents<SnakeGame> is a SnakeGame.
Inheritance work the other way around: a SnakeGame is indeed a KeyboardEvents<SnakeGame>. The other way is false.
I could show you how "to make it work", but a warning is needed here: you are overusing inheritance, and you used it the wrong way in the case of KeyboardEvent. You really should try to rearrange things around, or you'll end up in a real mess.
The solution "make it work"
Since you are using CRTP, you can tell the compiler that KeyboardEvents<SnakeGame> is indeed, in absolutely ALL cases, being extended by SnakeGame. If that's really the case, you can just static_cast your base class to the child class:
if(iterator!=mapOfDirects.end()){
// Notice the presence of the cast here
iterator->second->direction(static_cast<SnakeGame&>(*this));
mainDirection=codeFromKeyboard;
}
The slightly better solution
You can as well using an existing instance of your snake class as parameter.
void chooseMethodFromKeyboardArrows(sf::Keyboard::Key codeFromKeyboard, SakeGame& game){
auto iterator = mapOfDirects.find(codeFromKeyboard);
if(iterator!=mapOfDirects.end()){
iterator->second->direction(game);
mainDirection=codeFromKeyboard;
} else {
mapOfDirects[mainDirection]->direction(game);
}
}
However, the best idea is to not make SnakeGame extending KeyboardEvent, but to contain it in the class instead:
struct SnakeGame : Screen {
KeyboardEvent<SnakeGame> event;
void callEvents() {
event.chooseMethodFromKeyboardArrows(/* some key */, *this);
}
};
Here's an homework for you:
Try to make the class KeyboardEvent not a template. I'm sure you can find a way to pass around your class without the use of themplates, while still accessing directly to your class SnakeGame, without casts or interfaces.
Your design seems a bit overcomplicated. I think the reason this is so is perhaps you were designing it as you went along. Sometimes it helps to sit down and think about these things first, draw boxes and lines on a whiteboard if you have to.
In any case, this isn't a direct answer to your question, it's a suggestion for an alternative based on what I'm guessing you are trying to do.
It seems to me that you're trying to implement some generic keyboard input handler and tie it in to your game. It's possible that I'm entirely wrong about this, but if not, consider something like this instead. First, a generic interface for things that receive keyboard events. It need not be a template, this isn't really a good use-case for templates:
class KeyboardEventHandler {
public:
enum Direction { Left, Right, Up, Down };
virtual ~KeyboardEventHandler () { }
virtual void onDirectionKey (Direction d) = 0;
};
Now your SnakeGame, which handles keyboard events, can inherit that and implement its own SnakeGame-specific logic:
class SnakeGame : public KeyboardEventHandler {
public:
void onDirectionKey (Direction d) {
switch (d) {
case Up: ...
case Down: ...
case Left: ...
case Right: ...
}
}
};
And then whatever bit of code you have that is actually processing keyboard events and driving all of this can just work with a KeyboardEventHandler *, which could be a SnakeGame, or could be anything else you decide to use it for in the future.
That's just one possibility for organization. For example, you could structure it like this instead, breaking out the KeyboardEvent, which could simplify future additions:
class KeyboardEvent {
public:
enum Direction { Left, Right, Up, Down };
Direction getDirection () { ... } // or whatever
};
class KeyboardEventHandler {
public:
virtual ~KeyboardEventHandler () { }
virtual void onEvent (KeyboardEvent &event) = 0;
};
With SnakeGame as:
class SnakeGame : public KeyboardEventHandler {
public:
void onEvent (KeyboardEvent &event) {
...
}
};
You could name that stuff something else besides Direction / onDirectionKey if you want, I picked that from your example but just make it something semantically appropriate that is also convenient (e.g. if you plan on expanding it to include more than just the arrows). But whatever, that's beside the point.
There are also 10 zillion other ways to skin this cat but the important take-home point is: If you're trying to make some generic interface for something, you really can't make it rely on the specific details of what inherits it, otherwise you're defeating the purpose of making it general to begin with. In that case, either it's not a good case for generic bases / inheritance, or you've just botched the design and need to sit back and rethink.
Remember: Your goal isn't to add as many classes and stuff as possible to your code; you're not going for like, an inheritance high score. Your goal is to keep your code clean, readable, maintainable, correct, possibly reusable, and to make your work easier on yourself. These are tools, don't just use them because you have them, instead use them when you need them to make your life easier.
However, all that said, this is still overkill for your specific application, although it is an interesting exercise. To be honest, in your specific case, I'd just chuck all the inheritance and such altogether and do something like:
class SnakeGame {
public:
void handleKeyPress (char c) {
// ... do the right thing here
}
}
And be done with it.
I asked a couple days ago some clarifications on inheritance, a concept I am still trying to understand. Here is the follow up question, since I am still facing problems.
In my project I have 2 types of objects, Hand and Face, both inheriting from the base class BodyPart. BodyPart is something like this:
class BodyPart
{
public:
typedef boost::shared_ptr<BodyPart> BodyPartPtr;
BodyPart();
virtual ~BodyPart();
private:
int commonMember1;
double commonMember2;
public:
int commonMethod1();
int CommonMethod2();
}
while Hand is something like this:
class Hand : public BodyPart
{
public:
Hand();
~Hand();
private:
int numFingers;
double otherVar;
public:
int getNumFingers();
void printInfo();
}
I also have a vector of BodyPart elements
std::vector<BodyPart::BodyPartPtr> cBodyParts;
composed of Hand or Head objects. In the previous question I was told that this approach makes sense, I just had to cast from the base class to the derived using boost static_pointer_cast
Now, the problem now is that for some of the objects in the vector I don't know whether they are Hand or Head, so at some point in my code I can have in cBodyParts some Hand elements, some Head elements as well as some BodyPart elements. After some further analysis I am able to correctly classify the latter as either Hand or Head and modify accordingly the elements in the vector, but I have no idea on how to make it. Shall I just delete the case class element and create a derived one with the same property? Shall I just avoid inheritance in case like this?
Thanks in advance for the help
EDIT: I have augmented the examples to make them clearer.
Relaying on casts is usually a sign of a bad design. Casts have their place, but this does not look to be it.
You need to ask yourself what do you want to do with the objects stored in cBodyParts. For sure, you will be doing different things with a Hand or with a Head, but you can probably abstract them somehow: this is what virtual functions do. So, in addition to what you have already written for your classes, you would just need an additional virtual function in them:
class BodyPart
{
// Same as you wrote, plus:
public:
virtual void InitialisePart() = 0; // Pure virtual: each body part must say how to process itself
virtual void CalibrateJoints() {} // Override it only if the body part includes joints
}
class Head : public BodyPart
{
// Same as you wrote, plus:
public:
virtual void InitialisePart() {
// Code to initialise a Head
}
// Since a Head has no joints, we don't override the CalibrateJoints() method
}
class Hand : public BodyPart
{
// Same as you wrote, plus:
public:
virtual void InitialisePart() {
// Code to initialise a Hand
}
virtual void CalibrateJoints() {
// Code to calibrate the knuckles in the hand
}
}
And then you no longer need any casts. For instance:
for (BodyPart::BodyPartPtr part : cBodyParts) {
part->InitialisePart();
part->CalibrateJoints(); // This will do nothing for Heads
}
As you can see, no casts at all and everything will work fine. This scheme is extensible; if you later decide that you need additional classes inheriting from BodyPart, just write them and your old code will work correctly:
class Torso : public BodyPart
{
public:
virtual void InitialisePart() {
// Code to initialise a Torso
}
// The Torso has no joints, so no override here for CalibrateJoints()
// Add everything else the class needs
}
class Leg : public BodyPart
{
public:
virtual void InitialisePart() {
// Code to initialise a Leg
}
virtual void CalibrateJoints() {
// Code to calibrate the knee
}
// Add everything else the class needs
}
Now you don't need to change the code you wrote previously: the for loop above will work correctly with and Torso or Leg it finds with no need for an update.
The hip bone's connected to the thigh bone...
I take it you have some composite of all the body parts, maybe a Body class.
What do you want the body to do?
Render itself
Serialise
Ouput its volume, or bounding box, or some other metric
Re-orient itself in response to input
Respond to an inverse-kinematic physical model
The list could probably go on. If you know exactly what you want the Body to do you can put that function in the BodyPart base class, and have Body iterate over the composite hierarchical structure of all the connected body parts, calling render, for example.
An alternative is to use a Visitor, which is effectively a way of dynamically adding methods to a static inheritance hierarchy.
As Kerrek SB pointed out this is not feasible at all, but for the sake of answering the actual question, dynamic_cast is what you are looking for.
Use virtual functions, they will simplify a lot your problem.
Else, you can add some methods to distinguish between different types. However, do it only if you cannot do it another way, ie if you cannot do it via virtual functions.
Example 1:
// in BodyPart; to be reimplemented in derived classes
virtual bool isHand() const { return false; }
virtual bool isHead() const { return false; }
// in Hand (similar to what will be in Head)
bool isHand() const { return true; }
// How to use:
BodyPart::pointer ptr = humanBodyVector[42]; // one item from the array
if(ptr->isHand())
processHand(/*cast to hand*/)
else if(ptr->isHead())
// ...
Example 2: let the derived classes handle the cast
// in BodyPart; to be reimplemented in derived classes
virtual Hand* toHand() const { return 0; }
virtual Head* toHead() const { return 0; }
// in Hand (similar to what will be in Head)
Hand* toHand() const { return this; }
Let's say we already have a hierarchy of classes, e.g.
class Shape { virtual void get_area() = 0; };
class Square : Shape { ... };
class Circle : Shape { ... };
etc.
Now let's say that I want to (effectively) add a virtual draw() = 0 method to Shape with appropriate definitions in each sub-class. However, let's say I want to do this without modifying those classes (as they are part of a library that I don't want to change).
What would be the best way to go about this?
Whether or not I actually "add" a virtual method or not is not important, I just want polymorphic behaviour given an array of pointers.
My first thought would be to do this:
class IDrawable { virtual void draw() = 0; };
class DrawableSquare : Square, IDrawable { void draw() { ... } };
class DrawableCircle : Circle, IDrawable { void draw() { ... } };
and then just replace all creations of Squares and Circles with DrawableSquares and DrawableCircles, respectively.
Is that the best way to accomplish this, or is there something better (preferably something that leaves the creation of Squares and Circles intact).
Thanks in advance.
(I do propose a solution down further... bear with me...)
One way to (almost) solve your problem is to use a Visitor design pattern. Something like this:
class DrawVisitor
{
public:
void draw(const Shape &shape); // dispatches to correct private method
private:
void visitSquare(const Square &square);
void visitCircle(const Circle &circle);
};
Then instead of this:
Shape &shape = getShape(); // returns some Shape subclass
shape.draw(); // virtual method
You would do:
DrawVisitor dv;
Shape &shape = getShape();
dv.draw(shape);
Normally in a Visitor pattern you would implement the draw method like this:
DrawVisitor::draw(const Shape &shape)
{
shape.accept(*this);
}
But that only works if the Shape hierarchy was designed to be visited: each subclass implements the virtual method accept by calling the appropriate visitXxxx method on the Visitor. Most likely it was not designed for that.
Without being able to modify the class hierarchy to add a virtual accept method to Shape (and all subclasses), you need some other way to dispatch to the correct draw method. One naieve approach is this:
DrawVisitor::draw(const Shape &shape)
{
if (const Square *pSquare = dynamic_cast<const Square *>(&shape))
{
visitSquare(*pSquare);
}
else if (const Circle *pCircle = dynamic_cast<const Circle *>(&shape))
{
visitCircle(*pCircle);
}
// etc.
}
That will work, but there is a performance hit to using dynamic_cast that way. If you can afford that hit, it is a straightforward approach that is easy to understand, debug, maintain, etc.
Suppose there was an enumeration of all shape types:
enum ShapeId { SQUARE, CIRCLE, ... };
and there was a virtual method ShapeId Shape::getId() const = 0; that each subclass would override to return its ShapeId. Then you could do your dispatch using a massive switch statement instead of the if-elsif-elsif of dynamic_casts. Or perhaps instead of a switch use a hashtable. The best case scenario is to put this mapping function in one place, so that you can define multiple visitors without having to repeat the mapping logic each time.
So you probably don't have a getid() method either. Too bad. What's another way to get an ID that is unique for each type of object? RTTI. This is not necessarily elegant or foolproof, but you can create a hashtable of type_info pointers. You can build this hashtable in some initialization code or build it dynamically (or both).
DrawVisitor::init() // static method or ctor
{
typeMap_[&typeid(Square)] = &visitSquare;
typeMap_[&typeid(Circle)] = &visitCircle;
// etc.
}
DrawVisitor::draw(const Shape &shape)
{
type_info *ti = typeid(shape);
typedef void (DrawVisitor::*VisitFun)(const Shape &shape);
VisitFun visit = 0; // or default draw method?
TypeMap::iterator iter = typeMap_.find(ti);
if (iter != typeMap_.end())
{
visit = iter->second;
}
else if (const Square *pSquare = dynamic_cast<const Square *>(&shape))
{
visit = typeMap_[ti] = &visitSquare;
}
else if (const Circle *pCircle = dynamic_cast<const Circle *>(&shape))
{
visit = typeMap_[ti] = &visitCircle;
}
// etc.
if (visit)
{
// will have to do static_cast<> inside the function
((*this).*(visit))(shape);
}
}
Might be some bugs/syntax errors in there, I haven't tried compiling this example. I have done something like this before -- the technique works. I'm not sure if you might run into problems with shared libraries though.
One last thing I'll add: regardless of how you decide to do the dispatch, it probably makes sense to make a visitor base class:
class ShapeVisitor
{
public:
void visit(const Shape &shape); // not virtual
private:
virtual void visitSquare(const Square &square) = 0;
virtual void visitCircle(const Circle &circle) = 0;
};
What you're describing is somewhat like the decorator pattern. Which is very suitable to change runtime behaviour of existing classes.
But I don't really see how to implement your practical example, if shapes have no way to be drawn, then there's no way to change drawing behaviour at runtime either...
But I suppose this is just a very simplified example for stackoverflow? If all the basic building blocks for the desired functionality are available, then implementing the exact runtime behaviour with such a pattern is certainly a decent option.
One 'off the wall' solution you might like to consider, depending on the circumstance, is to use templates to give you compile time polymorphic behaviour. Before you say anything, I know that this will not give you traditional runtime polymorphism so it may well not be useful but depending on the limitations of the environment in which you're working, it can prove useful:
#include <iostream>
using namespace std;
// This bit's a bit like your library.
struct Square{};
struct Circle{};
struct AShape{};
// and this is your extra stuff.
template < class T >
class Drawable { public: void draw() const { cout << "General Shape" << endl; } };
template <> void Drawable< Square >::draw() const { cout << "Square!" << endl; };
template <> void Drawable< Circle >::draw() const { cout << "Circle!" << endl; };
template < class T >
void drawIt( const T& obj )
{
obj.draw();
}
int main( int argc, char* argv[] )
{
Drawable<Square> a;
Drawable<Circle> b;
Drawable<AShape> c;
a.draw(); // prints "Square!"
b.draw(); // prints "Circle!"
c.draw(); // prints "General Shape" as there's no specific specialisation for an Drawable< AShape >
drawIt(a); // prints "Square!"
drawIt(b); // prints "Circle!"
drawIt(c); // prints "General Shape" as there's no specific specialisation for an Drawable< AShape >
}
The drawIt() method is probably the key thing here as it represents generic behaviour for any class meeting the requirement of having a draw() method. Do watch out for code bloat here though as the compiler will instantiate a separate method for each type passed.
This can be useful in situations where you need to write one function to work on many types which have no common base class. I'm aware that this is not the question you asked, but I thought I'd throw it just as an alternative.