Suppose I have this base class:
struct Vehicle {
//"op" stands for the operator of the vehicle
//examples: pilot, truck driver, etc.
virtual void insert_op(Op op) = 0;
//other members...
};
And these two subclasses
struct Truck : public Vehicle {
void insert_op(Op op) override {
//prepare Truck with truck driver
}
};
struct Airplaine : public Vehicle {
void insert_op(Op op) override {
//prepare Airplaine with pilot
}
};
As you guess, this is the other hierarchy:
struct Op {};
struct TruckDriver : public Op {};
struct Pilot : public Op {};
You already see the problem, don't you? I want to FORCE Truck to accept only TruckDrivers and FORCE airplaines to accept only Pilots, but this is not possible in the current design. C++ does not allow diff parameters for overridden virtuals.
I guess I could do a run-time type check of the type of "Op" in each of the subclass implementations of insert_op, but that sounds like a really ugly solution, plus its not enforced at compile time.
Any ways out?
Your Vehicle says virtual void insert_op(Op op) which means "every vehicle can accept any Op".
Therefore, according to your design, a Truck isn't a valid candidate for a Vehicle subclass because it can't accept any Op - it can accept only TruckDrivers.
Related: Liskov substitution principle
The problem is in your design, not in implementation of it. I suggest to simplify your class hierarchy. Do you really need so many classes and inheritance? Can you simply go with Vehicle and Op that have fields identifying their type?
Let me further explain the design problem:
Assume some object A with a method manVehicle(Vehicle&). Truck is a subclass of Vehicle, so it's possible to call this method with an object of type Truck.
However, the implementation of A doesn't have a clue what concrete types of Vehicles. It only knows that all vehicles have a method insert_op(Op), so it's valid for it to attempt a call like insert_op(Pilot()) even if the vehicle is actually a Truck.
Conclusions:
Compile-time check isn't even possible
Runtime check could work...
but would only sweep the problem under the rug. An user of Vehicles expects to be able to call insert_op(Op) on any Vehicle.
A solution would be to modify the Vehicle interface to look like:
struct Vehicle {
virtual bool can_insert_op(Op op) = 0;
virtual void insert_op(Op op) = 0;
};
and document it so that the caller would know that insert_op can be only called with Ops that satisfy can_insert_op on the given Vehicle. Or something analogous (like a documented exception from insert_op "invalid op type for this vehicle") - anything works as long as it's a documented part of this interface.
BTW technical remark: You'd probably want these methods to take the Op by pointer or reference instead of copying it, to avoid an unnecessary copy as well as slicing.
The Vehicle subclasses should each create their their appropriate Operator. There should be no methods to set the operator. Vehicle could have a get_operator method, but that's about it.
I'm guessing this isn't your actual hierarchy (unless you're creating a game or something). If you show your actual hierarchy it might help with suggesting better solutions.
don't find against OOD. if truck driver is a child of driver then its a driver but has other features. in your case the driver is not allowed then its not sub truck driver. If you want to stick with the current design you need to make checks in the start of the fn as you assumed.
polymorphism is designed not to get errors #compile time hence it's dynamic binding at run time not compile time dependent.
What about:
struct Vehicle {
//"op" stands for the operator of the vehicle
//examples: pilot, truck driver, etc.
virtual void insert_op(Op op) = 0;
virtual bool validate_op(Op op);
//other members...
};
struct Truck : public Vehicle {
void insert_op(Op op) override {
if (validate_op(op)) {
//prepare Truck with truck driver
}
}
bool validate_op(Op op) override {
//check if this is a valid truck driver
return ( typeid(op)==typeid(TruckDriver) );
}
};
You would be able to keep the generic definition of insert_op with some validation over it.
What you want to accomplish is legitimate, however, there is no support for a good solution. It is not a problem of C++ itself, but of Object Orientation:
Your class hierarchy starting at Vehicle is covariant with respect to the hierarchy of Op. You'd have the same problem if you had a hierarchy of fuels. Or the nationality of the Ops, etc.
Others have told you explanations of how to accomplish this with run-time checks, but of course, there is always something to be desired.
If you want to accomplish full compile time checking, and the kind of polymorphism you want to have is at compilation time as opposed to runtime, you can use Generic Programming, templates.
Related
I have an idea to architecting classical entity-component in a better way with variadic template inheritance. This question stems from funky experiments in the context of 3d-graphics but i believe i have it broken down to a very abstract question about C++. I am able to use C++20 in the scope in which it is currently implemented in Microsoft cl aka. the MSVC++19-Toolchain.
So. A few Base classes:
class basic {
public:
std::wstring get_name() { return name; }
virtual void do_something_idk_virtual() = 0;
virtual ~basic() {}
private:
std::wstring name;
}
class has_legs {
public:
virtual void walk() = 0;
virtual ~has_legs() {}
}
class has_wings {
public:
virtual void fly() = 0;
virtual ~has_wings() {}
}
template<typename... Ts>
class entity : public basic, public Ts... {
public:
virtual ~entity() {}
}
So far, so good. Now i want to make a duck:
class duck : entity<has_wings, has_legs> {
public:
virtual ~duck() {}
virtual void walk() { cout << "walk" << endl; }
virtual void fly() { cout << "fly" << endl; }
virtual void do_something_idk_virtual() { } // nothing,
}
still, seems to work. The problem is: I know have data structure (say a linked_list, or some sort of graph) and I use the visitor-pattern to work with basic*-typed things. I now have a lot of Code that looks like this. This is, quite literally, the central and critical part of a my program:
void visit(basic* node) {
//here i find out, through magic or some other kind of out-of-scope-mechanism that node is at least a has_wings. Problem:
reinterpret_cast<has_wings*>(node)->fly(); //does not work, will call basic::do_something_idk_virtual(). As far as i understand, this is because the compiler-generated vtable does not change via the reinterpret_cast.
reinterpret_cast<entity<has_wings>*>(node)->fly(); //might, work, problems start to come in if node is of some type that has_wings and has_legs. It sometimes calls some other method, depending on the ordering in declaring the class.
}
Solution
Have every component (aka. the pure interfaces) and the entity-class virtually inherit from basic
in basic add the non-virtual method:
template<typename TComponent> TComponent* get_component() {
return dynamic_cast<TComponent*>(this);
}
This will then fix vtables. I am not sure why dynamic_cast does that.
First of all, your template gives you nothing. class duck : public basic, public has_wings, public has_legs is absolutely identical.
Second, you need to decide what your level of polymorphic access is. If your level is basic, than it has to have already defined all the virtuals you want to be accessing (i.e. has_wings, fly) An interface where you need dynamic_casts to arrive to correct dynamic type (your example with reinterpret_cast is just wrong, you can't use reinterpret_cast to move through class hierarchy) is a poorly written interface.
Sometimes visitor pattern can be employed, but in my mind, it tends to produce extremely hard to troubleshoot code.
You have to use static_cast or dynamic_cast to move within an inheritance hierarchy, and static_cast can’t descend virtual inheritance or cross-cast (in one step) because the layout of different classes that derive from the source and destination types may differ. As it is, you’d have to know the actual type (not just that it had a given aspect) to do the conversion. If you have your “aspect” classes inherit from basic—virtually, so that there is a unique basic* to be had—you can then use dynamic_cast not for its checking purpose but so as to find the appropriate vtable for the aspect in question.
If you can’t afford that, you may want to amalgamate the interfaces somehow. You then have to be careful to call the functions only when they’re meaningful; that’s already the case (“through magic”), but then the ordinary call syntax might be an attractive nuisance. You might also try some C-style polymorphism with a manually-created vtable with function pointers for each optional behavior.
I have a class hierarchy with lots of shared member functions in a base class, and also a large number of unique member functions in two derived classes:
class Scene {
public:
void Display();
void CreateDefaultShapes();
void AddShape(Shape myShape);
// lots more shared member functions
}
Class AnimatedScene : public Scene {
public:
void SetupAnimation();
void ChangeAnimationSpeed(float x, float y);
// lots of member functions unique to animation
}
Class ControllableScene : public Scene {
public:
void ConfigureControls();
void MoveCamera(float x, float y, float z);
void Rotate(float x, float y, float z);
// lots of member functions unique to a controllable scene
}
Not surprisingly, this doesn't work:
Scene myScene;
myScene.SetupAnimation();
What is the correct solution to this problem? Should I make all of the derived member functions virtual and add them to the base? Should I use a cast when calling SetupAnimation()? Is there a more clever design that solves this problem?
Note: I receive myScene from elsewhere and can't simply declare it as AnimatedScene when I instantiate it.
Edit: I've added a couple more member functions to illustrate the point. A small handful of initialization functions definitely lend themselves to simply using virtual.
You can cast it, preferably using static_cast. The least preferable option. If you are casting things, it usually means your design needs more thought
If you have a particular function/class that needs one or the other, declare the input as the type you need, which more accurately communicates the requirements of the function or class
If the function needs to be generic, and those methods don't require any input, then you could define a virtual method in the parent class, say init, which in the derived classes call the correct methods to set up the instance.
I have a similar problem in my compiler project, where the AST (Abstract Syntax Tree) is constructed from the statements, so while(x != 0) { if (a == b) x = 0; } would construct a whileAST with a binaryExpr inside it, then a blockAST with the ifAST, and so on. Each of these have some common properties, and a lot of things that only apply when you actually do something specific to that part. Most of the time, that is solved by calling a generic (virtual) member function.
However, SOMETIMES you need to do very specific things. There are two ways to do that:
use dynamic_cast (or typeid + reinterpret_cast or static cast).
Set up dozens of virtual member functions, which mostly are completely useless (doesn't do anything or return an "can't do that" indication of some sort)
In my case, I choose the first one. It shouldn't be the common case, but sometimes it is indeed the right thing to do.
So in this case, you'd do something like:
AnimatedScene *animScene = dynamic_cast<AnimatedScene*>(&scene);
if (!animScene)
{
... do something else, since it's not an AnimatedScene ...
}
animScene->SetupAnimation();
I am not yet able to comment, which is what I really wanted to do, but I am also interested in figuring this out as well.
A few months ago I had a similar problem. What I can tell you is that you can use typeid operator to figure out what type the object is, like so:
int main()
{
scene* ptr = new AnimatedScene();
if (typeid(*ptr) == typeid(AnimatedScene))
{
cout<<"ptr is indeed a animatedScene"<<endl;
AnimatedScene* ptr2 = (AnimatedScene*)(ptr);
ptr2->SetupAnimation();
}
else
{
cout<<"not a animatedscene!!!"<<endl;
}
}
This works, you'll then be able to use ptr2 to access the animatedScene's unique members.
Notice the use of pointers, you can't use the objects directly, due to something called "object slicing" when playing with polymorphism: https://en.wikipedia.org/wiki/Object_slicing
Like you I have heard something about the use of typeid and thus, casting being a bad idea, but as to why, I cannot tell you. I am hoping to have a more experienced programmer explain it.
What I can tell you is that this works without problems in this simple example, you've avoided the problem of declaring meaningless virtual functions in the basetype.
Edit: It's amazing how often I forget to use google: Why is usage of the typeid keyword bad design?
If I understand mr Bolas correctly, typeid incentivizes bad coding practices. However, in your example you want to access a subtypes non-virtual function. As far as I know, there is no way of doing that without checking type at compiletime, ie typeid.
If such problem arises with your hierarchy that proves that hierarchy was too generalized. You might want to implement interfaces pattern, if class have certain functionality, it would inherit an interface that defines that functionality.
Proven that dogs are animals, do all animal but dogs fail to bark, or do only dogs bark?
The first approach lead to a class animal failing all the verses of the entire zoo, implemented one-by one in each animal. And in particular class dog will override just bark().
In this approach animal becomes a sort of "god object" (knows everything), requiring to be constantly updated every time something new is introduced, and requiring It's entire "universe" to be re-created (recompile everything) after it.
The second approach requires first to check the animal is a dog (via dynamic cast) and then ask it to bark. (or check for cat before asking a mieow)
The trade-off will probably consist in understanding how frequent is the possibility you have to check a bark out of its context (not knowing which animal are you deal with), how to report a fail, and what to do in case of such fail.
In other words, the key driver is not the bark, but the context around it inside your program.
//Are you trying to do something like this?
class Scene{
public:
virtual void Display()=0; //Pure virtual func
};
class AnimatedScene : public Scene{
public:
void Display(){
std::cout<<"function Display() inside class AnimatedScene" <<std::endl;
}
};
class ControllableScene : public Scene{
public:
void Display(){
std::cout<<"function Display() inside class ControllableScene" <<std::endl;
}
};
int main(){
AnimatedScene as;
ControllableScene cs;
Scene *ex1 = &as;
Scene *ex2 = &cs;
ex1->Display();
ex2->Display();
return 0;
}
Consider an abstract class called Vehicle. This vehicle has following abstract operations
- Start
- Break
- Accelerate
class Vehicle
{
public:
virtual void Start() = 0;
virtual void Break() = 0;
virtual void Accelerate() = 0;
};
Now consider that we have a special kind of vehicle derived from Vehicle class namely VehicleA.
Class VehicleA: public Vehicle
{
private:
double speed;
double temperature;
int id;
double miles;
public:
void Start();
void Break();
void Accelerate();
void horn();
};
If I now have a vehicle which is almost similar to VehicleA type but slightly differs in say the type of engine or some other characteristics like color, which is the best way to accommodate such a small change in the class hierarchy design. Should I
define another class VehicleB derived from Vehicle class ? or
define another class VehicleB derived from VehicleA ? or
something else ?
Thanks
In this case, you really should consider composition over inheritance.
Depending on what the class Vehicle actually means to you (and be careful with that, intuition isn't necessarily your best friend when going through this kind of class design : think about the famous Square/Rectangle case), you could have your VehicleA declared the following way (don't forget the virtual keyword):
class VehicleA: public Vehicle
{
private:
//Your specific private
Engine* m_engine;
Color* m_color;
//Add any "modifiable" part as long as it fits
public:
virtual void Start();
virtual void Break();
virtual void Accelerate();
void horn();
};
with Engine and Color two classes (that can be abstract or not) that hold the details you want to implement.
You add another level of abstraction : your VehicleA has an engine (with its own interface), but don't care about its details (as long as the engine has an interface the vehicle can interact with), and makes it possible to add easily a new type of engine.
As a general rule when designing a hierarchy, if you think you must implement a new derived class of a specific class, ask yourself the following :
Is this class a more specific version of its parent class ?
In your case, it feels like a VehicleB wouldn't be a more specific version of a VehicleA though that's still a matter of opinion, as it completely depends on what you want to do. In this case, it feels like the way to go should be composition.
What you have here is a problem related to "Separation of Concerns". The "Vehicle" concept has a few basic operations some of which you identify, for example "Accelerate". Now the implementation of "Accelerate" is dependent on certain parameters, such as maximum torque, brake-horsepower etc...
These should should be encapsulated outside of the vehicle... but why? Well because they the Vehicle represents a concept, not an implementation. Accelerating will use an engine in the same manner, no matter what that type of car involved. let me use a real-world example:
A McClaren F1 is a Vehicle, in fact it is a car, which contains an engine, has a chassis, has some tyres and suspension etc...
A Volkswagon Golf GTI is a Vehicle, in fact it is a car, which contains an engine, has a chassis, has some tyres and suspension etc...
The user will drive one car in the exact same manner as another car, even if it has hugely different sets of component parts. The user does not need to even be aware of most of the details. This is why you need to separate out your Vehicle concept from the implementation details that are encapsulated by the specific components of your Vehicle.
You should do the same for your "Brakes" as well, and you should inject the Engine and Brakes into the Vehicle at construction (look up Dependency Injection).
Now for colour: I would recommend that you place this at the top level of your class hierarchy, in the Vehicle abstract class. It is something that applies to all classes of vehicles, and is used in the same way by all, and does not affect any implementation. It should be set via the constructor probably, with a repaint function offered for changing it (once the necessary fees are passed to the Garage via the SalesPoint of course!).
So the class in the end might look like this...
class Vehicle
{
private:
std::unique_ptr<Engine> engine;
std::unique_ptr<Brake> brakes; // same for "Suspension", "Chassis" etc...
VehicleColour colour; // An enum defined here or elsewhere.
public:
Vehicle( std::unique_ptr<Engine> engine, std::unique_ptr<Brake> brakes, VehicleColour colour)
: this->engine(std::move(engine)),
this->brakes(std::move(brakes)),
this->colour(colour) {
}
virtual void Start(const Key& key) {
engine->ignition( key );
brakes->disengage();
}
virtual void Break( BreakPattern pattern ) {
engine->setThrottlePosition( NO_THROTTLE );
brakes->engage( pattern ); // e.g. SIMPLE_HARMONIC, or SLAM... brakes may have ABS or not but you don't need to know
}
virtual void Accelerate() {
brakes->disengage();
engine->setThrottlePosition( TO_THE_METAL );
}
};
Using it:
std::unique_ptr<Brake> absBrakes( new VwAbsDiskBrakes() );
std::unique_ptr<Engine> fastEngine( new TurboV8( FOUR_LITRE ) );
Vehicle hotrod( absBrakes, fastEngine, RED );
hotrod.start();
hotrod.accelerate();
It uses the components via their interfaces, so it doesn't need to know specifics. The sub-classes of Vehicle then do not need to worry about anything that is not Vehicle specific. You will only need a subclass of Vehicle if there is a vehicle that does not fit your generic concept a vehicle (for example if there is a vehicle out there with no brakes).
How to handle classes that are slightly different?
This depends completely on what you are trying to solve. The Vehicle class isn't a real car, it is a model based on information of the real world, needed to make a working program. It is not one set of fixed rules.
About the color: this has nothing to do with the behavior of the class, so if possible ignore it, if not, make an extra field.
About the type of engine: does this make a noticeable difference to the behavior or is it just a matter of setting some parameters (power, couple, fuel consumption)? In case of the engine, there is a good chance that you can have a hierarchy of engines that can be contained in the vehical.
Recently I was given a task where I had to implement something similar to the following:
There are some animals with certain attributes, such as:
Dog1: name: tery, color:white, fav drink: grape juice
Dog2: name: chiva, color:black, fav drink: lemonade
Bird1: name: tweety, canfly: yes, cansing: no
Bird2: name: parry, canfly: no, cansing: yes
How would you do this in C++ efficiently using OOP prractices?
I did something like this:
class Animal {
Animal(...);
...
public String getName() const;
public void setName(string s);
...
private:
String name;
}
class Bird : public Animal {
Bird(...);
public bool canFly() const;
public void setCanFly(bool b);
...
private:
bool canFly;
bool canSing;
}
class Dog : public Animal {
...
}
The problem with this implementation is that i cannot benefit from polymorhism :
Animal* p = new Anima(...);
...
p->canFly();
and I have to use casting:
((Bird*)p)->canFly();
At the end I was criticized of not using virtual functions in base class, and using casts instead of OOP.
But in my opinion it doesn't make sense to use virtual functions here because getName() should be in the base class to avoid multiple implementations of same method. And canFly is not a valid property for dogs for example.
Then I would have to define something absurd like this for each other (future) animal that also inherits from the base class, which would create unnecessary overhead:
bool Dog::canFly () const {
return false;
}
Who is right here, did I not get the basic principles of polymorphism?
Of course 'canFly' is a valid property for a dog, it's just going to return false.
There's no point in having canFly at all if you only implement it when it needs to be true. In your example, by the time you've done your c-style case to a flying animal, then you've already committed to the type of animal, at which point you don't really need to call canFly, because you already know the answer.
If you really don't want to implement canFly in a large number of non-flying animals, then implement virtual bool canFly() const { return false; } in your base class, and just override it in the flying animals.
I'd assume that this is just a contrived 'homework' question, so the answer is bound to look contrived too, but a style which involves lots of casting object types is really going to be bad news in real work.
Well, you don't need a single base class. Consider this:
Animal
|
|--Flying Animal
| |---Bird
|
|--Non Flying Animal
|---Dog
where:
class Animal
{
public:
virtual bool CanFly () = 0;
String Name ();
};
class Flying : public Animal
{
public:
virtual bool CanFly () { return true; }
};
class NonFlying : public Animal
{
public:
virtual bool CanFly () { return false; }
};
class Bird : public Flying
{
};
class Dog : public NonFlying
{
};
There are many other ways to do this as well, even using composition rather than inheritance.
EDIT: Composition. Having a hierarchy where each level in the hierarchy represents a smaller group of members (there are fewer dogs than animals) presents the problem of how to divide the set of all possible types into a hierarchy. As Lagerbaer pointed out in the comments, some birds can't fly.
So instead of creating a complex tree, have a simple tree (or no tree) and have each animal contain a list of characteristics of that animal:
class Animal
{
public:
String Name ();
List <Characteristic> Characteristics ();
};
class Characteristic
{
public:
String Name ();
};
class CanFly : public Characteristic
{
public:
bool CanFly ();
};
class Legs : public Characteristic
{
public:
int NumberOfLegs ();
};
And then, to create a dog:
Animal *CreateDog ()
{
Animal *dog = new Animal;
dog->Characteristics ()->Add (new CanFly (false));
dog->Characteristics ()->Add (new NumberOfLegs (4));
return dog;
}
and to create a bird:
Animal *CreateBird ()
{
Animal *bird = new Animal;
bird->Characteristics ()->Add (new CanFly (true));
bird->Characteristics ()->Add (new NumberOfLegs (2));
return bird;
}
There are two advantages to this:
You can extend it to add whatever characteristics you want.
You can drive the creation of animals from data rather than hard coding it all.
If your language of choice supports reflection, then searching the characteristics list is very straightforward. In non-reflection languages, you'll need to implement some way to identify what each characteristic is.
To address the technical issue, this is wrong:
((Bird*)p)->canFly();
This C-style cast performs a static_cast; if p points to a Dog, the cast will succeed but the result will be incorrect. Bad Things Happen.
When you don't know the most derived type of the pointed-to object and you don't have some way of determining its type via the base class pointer, you need to use dynamic_cast:
if (Bird* bp = dynamic_cast<Bird*>(p)) {
// p points to a Bird
}
else {
// p points to something else
}
dynamic_cast returns a null pointer if the cast fails, allowing you to check the type of the object.
To address the design issue, it depends. In real-world software you can't always have virtual functions in the base class that define the behavior of every possible derived class. It's just not possible. Sometimes it is necessary to dynamic_cast to a derived class to be able to call functions not declared in the base class.
Casts probably were not necessary in this very simple case, but if you were to consider a more complete class hierarchy defining the animal kingdom, you'd find that you would either need an enormous number of functions in the Animal base class or you would have to use casts at some point.
Virtual methods only make sense where there is a need for subclasses to provide their own implementation, or to force them to (pure virtual).
In the case of your canFly and canSing usage, where data members in the base class support invariant implementation in all subclasses, making those get/set methods virtual makes no sense at all to me.
A better candidate for virtual would be the corresponding fly and sing methods, where base class implementation might throw and only when the properties are set true would an animal-specific implementation be provided in a subclass.
struct Animal {
std::string name;
std::string favoriteDrink;
bool canFly;
bool canSing;
};
Feel free to wrap get/setters around the members if it makes you happy.
But one thing people tend to forget is that polymorphism is about behavior. It is about making different classes that look the same, but behave differently.
In this example, there is no different behavior between any of the animals, and so making more than one class is overkill.
There is no actual behavior required for any of the animals. The only operations we need are the ability to ask "what is its name", "can it fly", "can it sing" (and of course, "will it blend?")
All of these operations make as much sense for a penguin as they do on a terrier, a blue whale or a shrew. The behavior is the same, only the data changes. And so it should be one class, with different instances for different animals.
And so trying to split them into separate classes goes against all the goals of OOP: you end up intentionally duplicating code, doing less code reuse, and you're making your code less polymorphic, not more. In my solution, any animal is a drop-in replacement for any other animal. Once you start messing about with different classes and virtual methods, you have to actually write new code for each new animal in order for it to be a suitable implementation of the Animal base class.
If you ever need to add the actual Fly() method, you might need different classes. The mechanics of flying are different for a sparrow, an eagle and a bat (although even this depends on the objective. Depending on what abstraction level the application is working on, the "fly" routine might consist of nothing more than setting another bool flag somewhere, or perhaps giving the animal a positive non-zero altitude, in which case the same implementation is reusable for any flying animal).
But at the moment, all we need is the ability to ask whether or not an animal can fly. And the implementation of that is trivially reusable.
But of course, it's clear from the task you were given that the correct answer (where "correct" is defined as "the I expected when I asked the question" is "use lots of virtual methods for everything, and give everything its own class".
Which just goes to show that the more OOP zealotry you get from someone, the lower the odds that they actually understand OOP.
See also my blog post on the topic
It might be too much in that simple case, but later on you could keep all your animals in a linked list (or standard list or array or whatever) and then iterate over all entries and just call the base methods to do all kinds of stuff without having to worry about casts.
Just think of a simple game with GameObject being the base class and the Methods update() and draw() being virtual. You then inherit other classes, e.g. PlayerObject, EnemyObject, PowerUpObject, etc.
In your main loop you could then do something like this:
GameObject *p = firstObject;
while(p)
{
p->update();
p = p->nextObject;
}
This will iterate over all game objects and call the proper update() methods (e.g. moving the player, letting a power up spin or whatever) and you don't have to do some special casting, e.g. checking to see if it's a player or whatever.
I think you are right. Adding every conceivable property that some family of animals can have to a base class Animal is plain silly and produces too much overhead.
Although it is clear what was intended in the task, i.e., that you really have a virtual function canFly in the base class, I think this is poor design.
Declaring something virtual doesn't stop you implementing it in the base class.
It's a mechanism for saying that you should use the most specific implementation available. It is distinct from over-riding the implementation in the derived class.
Why should returning false from canFly() for a dog be a problem? Some birds can't fly and there are non-birds that can fly.
In my humble opinion, having getter and setter methods is indicative of poor object-oriented design. And this problem space is not particularly conducive to showing off what good object-oriented design is either.
(This question should probably be answered with a reference to Stroustrup.)
It seems extremely useful to be able to request a pointer to the most derived class, as in the following:
class Base { ... };
class DerivedA { ... };
class DerivedB { ... };
class Processor
{
public:
void Do(Base* b) {...}
void Do(DerivedA* d) {...}
void Do(DerivedB* d) {...}
};
list<Base*> things;
Processor p;
for(list<Base*>::iterator i=things.begin(), e=things.end(); i!=e; ++i)
{
p.Do(CAST_TO_MOST_DERIVED_CLASS(*i));
}
But this mechanism isn't provided in c++. Why?
Update, Motivating Example:
Suppose instead of having Base and Derived and Processor, you have:
class Fruit
class Apple : public Fruit
class Orange: public Fruit
class Eater
{
void Eat(Fruit* f) { ... }
void Eat(Apple* f) { Wash(f); ... }
void Eat(Orange* f) { Peel(f); ... }
};
Eater me;
for each Fruit* f in Fruits
me.Eat(f);
But this is tricky to do in C++, requiring creative solutions like the visitor pattern. The question, then, is: Why is this tricky to do in C++, when something like "CAST_TO_MOST_DERIVED" would make it much simpler?
Update: Wikipedia Knows All
I think Pontus Gagge has a good answer. Add to it this bit from the Wikipedia entry on Multiple Dispatch:
"Stroustrup mentions that he liked the concept of Multi-methods in The Design and Evolution of C++ and considered implementing it in C++ but claims to have been unable to find an efficient sample implementation (comparable to virtual functions) and resolve some possible type ambiguity problems. He goes on to state that although the feature would still be nice to have, that it can be approximately implemented using double dispatch or a type based lookup table as outlined in the C/C++ example above so is a low priority feature for future language revisions."
For background, you can read a little summary about Multi-Methods, which would be better than a call like the one I mention, because they'd just work.
Probably because that's what virtual functions do for you instead. The implementation of the virtual function that is nearest the most-derived class will be called when you invoke it through a base class pointer or reference.
Firstly, C++ does allow you to request a pointer to a most derived class in numerical terms (i.e. just the numerical value of the address). This is what dynamic_cast to void* does.
Secondly, there's no way to obtain a pointer to the most derived class in therms of exact type of the most derived class. In C++ casts work with static types, and static type is a compile-time concept. Type-based function overloading is also a compile-time process. The exact most derived type is not known at compile-time in your case, which is why cannot cast to it and can't resolve overloading on it. The request to have such a cast makes no sense in the realm of C++ language.
What you are trying to implement (if I understood your intent correctly), is implemented by completely different means, not by a cast. Read about double dispatch, for one example.
Because the type of i is not determinable at compile time. Therefore the compiler would not know which function call to generate. C++ only supports one method of dynamic dispatch that is the virtual function mechanism.
What you are suggesting would be equivalent to a switch on the runtime type, calling one of the overloaded functions. As others have indicated, you should work with your inheritance hierarchy, and not against it: use virtuals in your class hierarchy instead of dispatching outside it.
That said, something like this could be useful for double dispatch, especially if you also have a hierarchy of Processors. But how would the compiler implement it?
First, you'd have to extract what you call 'the most overloaded type' at runtime. It can be done, but how would you deal with e.g. multiple inheritance and templates? Every feature in a language must interact well with other features -- and C++ has a great number of features!
Second, for your code example to work, you'd have to get the correct static overload based on the runtime type (which C++ does not allow as it is designed). Would you like this to follow the compile time lookup rules, especially with multiple parameters? Would you like this runtime dispatch to consider also the runtime type of your Processor hierarchy, and what overloads they have added? How much logic would you like the compiler to add automatically into your runtime dispatcher? How would you deal with invalid runtime types? Would users of the feature be aware of the cost and complexity of what looks like a simple cast and function call?
In all, I´d say the feature would be complex to implement, prone to errors both in implementation and usage, and useful only in rare cases.
It's called using a virtual function call. Pass the processor* into DerivedA/B's virtual method. Not the other way around.
There is no mechanism provided because it's totally unnecessary and redundant.
I swear, I fielded this exact question about a day or two ago.
In C++ overload resolution happens at compile time. Your example would require determining the real type of *i at runtime. For it to be done at runtime would require a runtime type check, and because C++ is a performance oriented language it purposefully avoids this cost. If you really wanted to do this (and I'd be curious to see a more realistic example) you could dynamic_cast to the most derived class, then if that fails to the second most derived class, and so on, but this requires knowing the class hierarchy up front. And knowing the full hierarchy up front maybe impossible -- if the DerivedB class is in a public header, it's possible another library uses it and has made an even more derived class.
You're looking for double dispatch. It can be done in C++, as shown at that link, but it's not pretty, and it basically involves using two virtual functions calling each other. If you can't modify some of the objects in your inheritance tree, you may not be able to use this technique either.
This is not possible in C++, but what you want to achieve is easily doable using the Visitor design pattern:
class Base
{
virtual void accept(BaseVisitor& visitor) { visitor.visit(this); }
};
class DerivedA
{
virtual void accept(BaseVisitor& visitor) { visitor.visit(this); }
};
class DerivedB
{
virtual void accept(BaseVisitor& visitor) { visitor.visit(this); }
};
class BaseVisitor
{
virtual void visit(Base* b) = 0;
virtual void visit(DerivedA* d) = 0;
virtual void visit(DerivedB* d) = 0;
};
class Processor : public BaseVisitor
{
virtual void visit(Base* b) { ... }
virtual void visit(DerivedA* d) { ... }
virtual void visit(DerivedB* d) { ... }
};
list<Base*> things;
Processor p;
for(list<Base*>::iterator i=things.begin(), e=things.end(); i!=e; ++i)
{
(*i)->visit(p);
}
Why doesn't C++ have it? Perhaps the creators never thought about it. Or perhaps they didn't consider it suitable or useful enough. Or perhaps there were problems with actually trying to do it in this language.
On that last possibility, here's a thought experiment:
Lets say the this feature exists so that the compiler will write code that examines the dynamic type pointed to and calls the appropriate overload. Now lets also say a separate portion of the code has class DerivedC : Base {...};. And say that the corresponding Processor::Do overload is not added.
Given all of that, what should the program do when it tries to choose the appropriate overload? This discrepancy cannot be caught at compile-time. Should it try to climb the class hierarchy to find a function that matches a base class? Should it throw a special exception? Should it just crash? Is there some other possibility? Is there actually any reasonable choice that the compiler could make on its own without knowing the intention of your code and class hierarchy?
Yes, writing such functionality yourself would be susceptible to the same problem, but there the programmer has total control to choose the behavior, not the compiler.
C++ interprets data in the context of the associated type. When you store an instance of DerivedA* or DerivedB* in a list, that associate type must necessarily be Base*. This means that the compiler itself can no longer determine that those are pointers to one of the subclasses rather than the base class. While in theory you could cast to a LESS derived class by looking at the associated type's inheritance, the information needed to do what you want simply isn't available at compile-time.