So this is probably a weird question, but I have a reasonably good reason for asking.
The gist of my question is, given an example with two levels of derivation on a class hierarchy:
Main Base Class:
class Animal
{
virtual void Draw() = 0;
};
Derived Class:
class Dog : public Animal
{
virtual void Draw()
{
// draw a generic dog icon or something...
}
};
Further Derivation:
class Corgi : public Dog
{
virtual void Draw()
{
// draw a corgi icon...
}
};
Now, I'd love to be able to, from within the Corgi class, permanently downcast the 'this' pointer to a Dog pointer and then pass it off somewhere else as an Animal. This other place will then be able to call the Draw function and get the Dog method, not the virtual Corgi method. I know this is strange, but again, I have a vaguely legitimate reason for wanting to do it.
I've tried all the different casting operators and haven't had any luck, but maybe there is a consistent way of pulling this off? In the past I've caused myself trouble by not properly using dynamic_cast which resulted in a similar state for a pointer. Perhaps this time I can use that to my advantage?
Edit:
Perhaps the above example doesn't illustrate clearly the what I'm trying to achieve, so I'll elaborate with my real goal.
I'm trying to achieve a shorthand for registering base class implementations that link into a scripting system I've been using for a while. The scripting system relies on a base class IScriptContext to facilitate access to real-code functions and member variable access. Internally base classes register their member function addresses and member variable addresses which are later dispatched/accessed through lookup tables. I'm in the process of adding proper support for class derivation hierarchies to the scripting system, and I figured being able to isolate the base class versions of these interfaces would help save time and make the whole process cleaner for me when it comes time to register available base classes with the script interpreter. There are other ways to achieve this, such as registering class specific function pointers for each required method for each available base class (e.g. this->Dog::CallFunction, this->Dog::SetMember, this->Dog::GetMember.) However, I figured using an interface would allow me to modify things a bit easier down the road if I ever needed to.
I hope all of that makes some kind of sense.
Thanks!
You have a Corgi object. You can:
Treat it as a Dog object everywhere by using the Dog:: qualifier to all calls (e.g. ptr->Dog::draw();). This loses you virtual dispatch, and is almost certainly not what you want from how your question reads.
Actually construct a new Dog object from your Corgi. Just do this with a normal static_cast as you'd convert any other type or let implicit conversion take over (e.g. Corgi c; Dog d(c);).
These are the options available to you. To want to retain a Corgi but automatically pretend everywhere that it's a Dog is neither reasonable nor legitimate, so the language does not provide for it.
Let me start off by saying your design looks faulty.
You can however explicitly say which function in a hierarchy you want to call:
Corgi* corgi = new Corgi;
corgi->Dog::draw();
This will call the draw method from Dog, not from Corgi. (I hope I understood correctly what you're asking).
Tomalak has already outlined two of the main choices available to you:
use qualified calls, or
construct a Dog as a Dog copy of your Corgi.
In addition to these, you can
use a simple wrapper
e.g.
class LooksLikeDog
: public Dog
{
private:
Dog* realObject_;
LooksLikeDog( LooksLikeDog const& ); // No such.
LooksLikeDog& operator=( LooksLikeDog const& ); // No such.
public:
LooksLikeDog( Dog& other )
: realObject_( &other )
{}
// Just for exposition: not implementing this does the same.
virtual void draw() override { Dog::draw(); }
// Example of other method that may need to be implemented:
virtual void bark() override { realObject_->bark(); }
};
But the best solution is most probably to fix your design. ;-)
Implement Corgi draw function and call your parent's implementation:
virtual void Corgi::Draw()
{
Dog::draw();
}
Related
Suppose we have a class, "Animal", and subclasses, "Cat" and "Dog".
Let's say we want to allow both "Cat" and "Dog" to make a noise (cat: "meow" - dog: "woof") when we pass their objects into an intermediate function for any "Animal".
Why must we use a virtual method to do this? Couldn't we just do Animal->makeNoise() without defining a virtual method in "Animal"? As "Cat" and "Dog" are both animals, wouldn't it be clear that "makeNoise()" is referring to the Animal which has been passed to the function?
Is this just a matter of syntax or something more? I'm pretty sure in Java we don't have to do this.
In Java, all member functions are virtual by default (except static, private, and final ones).
In C++, all member functions are non-virtual by default. Making functions virtual adds overhead - both runtime and to object size - and the C++ philosophy is don't pay for what you don't use. Most of my objects are not polymorphic, so I shouldn't have to pay for polymorphism unless I need it. Since you need Animal::makeNoise() to be virtual, you must explicitly specify it as such.
C++ is designed to run with as little overhead as possible, trusting the programmer to make the correct call. Essentially, it 'gives you the gun and the option to shoot yourself in the foot', as one of my friends likes to say often. Speed and flexibility are paramount.
To correctly cause true polymorphic behavior, C++ requires it be specified. However! It is only required to be specified in the base class, as all derived class will inherit the virtual member functions. If a member inherits a virtual member function, it is good practice to place 'virtual' in the declaration, but not required.
ADTs usually implement pure virtual functions to indicate that the derived classes MUST implement the function. Such as:
animal makeNoise() = 0; /*Indicates this function contains no implementation.
and must be implemented by derived classes in order to function.*/
Again, it is not required the derived classes include 'virtual' in their inherited members so long as the base class includes this.
If you want to deduce the type of the Animal and then call make_sound(), then you would have to do a dynamic_cast on the animal object for each and every child of animal. This would include any class that is directly or indirectly a child of the Animal class.
This is both difficult to maintain and very painful to any change eg. Adding new class as a child to the Animal class.
Since c++ philosophy is efficiency, you will have to ask the compiler to provide you with run-time polymorphism as it is costly. How would you do that? By stating the make_sound() function as virtual. This creates a vtable ( a table of functions pointers ) which refers to an address of make_sound() which differs to based on the type of the object.
No need to downcast as indirection handles everything for you. What could be hundreds of lines of code is just a single line of code. That is the power of indirection!!
You could say that you have to do it because that's one of the rules of the language.
There's a reason its helpful though.
When trying to validate the code that uses an Animal, the complier knows what functions exist on an Animal. Its possible to tell whether the code is correct without checking all classes that derive from animal. So that code doesn't need to depend on all those derived classes. If you derive a new class from Animal but forget to implement the makeNoise function that's an error in the new class not the code that uses the Animal base class and the complier can point you towards that error. Without the virtual function declared in Animal there would no way to tell if its the calling code or the new class that is in error.
A key point here is that these errors would be caught at compile-time for C++ because of its static typing. Other languages can allow dynamic typing, which can make some things easier but, the errors would only be spotted at runtime.
In Java, all functions are virtual by default. In C++ they are not, so when you call a non-virtual function on a pointer of a given type, that type's implementation of that function is invoked with the object's address as this.
class Animal {
public:
void sound() { std::cout << "splat\n"; }
virtual void appearance() { std::cout << "animaly\n"; }
};
class Cat {
public:
void sound() { std::cout << "meow\n"; }
virtual void appearance() { std::cout << "furry\n"; }
};
int main() {
Animal a;
Cat c;
Animal* ac = new Cat;
a.sound(); // splat
a.appearance(); // animaly
c.sound(); // meow
c.appearance(); // furry
ac->sound(); // splat
ac->appearance(); // furry
}
This would occur when you wanted to write a function that generalized on "Animal" rather than requiring a specific derived class pointer.
In java you use virtual methods too.
It improves the loosely coupling of your software.
For example, you can use a library and don't know which animal they use internally. There is a animal implementation you don't know and you can use it because it's an animal. You get the animal with a library.getAnimal method. Now you can use their animal without to know which noise it makes, because they have to implement the method makeNoise.
Edit: So to answer your question, c++ wants a explicit declaration and in java it is implicit. so yes it is a kind of language specific idiosyncracy.
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;
}
//Parent.h
class Parent
{
public:
virtual void foo() = 0;
};
//Child.h
class Child : public Parent
{
public:
virtual void foo(){cout << "inside function foo()" << endl;}
virtual void bar(){cout << "inside function bar()" << endl;};
};
int main( int argc, char** argv ){
Parent* pa = new Child;
pa->foo();
pa->bar(); //Error, class Parent have no member bar
return 0;
}
How do i avoid this error other than add those function to the Parent class
You can declare your pointer as Child type. You will still be able to pass it to function expecting a Parent pointer.
Other solution involves using dynamic_cast<Child>(pa) although this is often seen as bad design to need this because it defeats what polymorphism is supposed to accomplish.
You can use static or dynamic_cast. Example with dynamic_cast:
if (Child* child = dynamic_cast<Child*>(pa))
child->bar();
You avoid this error by being more careful in your class design in the first place.
Yes, you can use dynamic_cast or static_cast to cast a Base pointer to a Derived pointer if the types are related, as they are here. But let's think about this.
Q: Why do you use polymorphism?
A: To provide different behaviour for similar operations, where the behaviour is selected at run-time.
Polymorphism is used to abstract away the implementation of an operation from the provision of that operation. All Shapes for example have a number of sides. How many sides depends on the actual shape, but we shouldn't have to know what kind of Shape something is in order to ask it how many sides it has. We should be able to just ask it.
Q: Why do you typically need to use dynamic_cast?
A: Because the base pointer doesn't provide the facilities you need.
If we shouldn't have to care what kind of Shape some object is in order to carry out the operations we need on it, then why would the Shape interface ever not provide whatever facilities we need?
This happens when we've made a mistake in designing something. Either Shape didn't have enough or the right kinds of facilities in it, or some particular Shape subclass is trying to do more than it should.
That's what you've done here. If it doesn't make sense for Parent to have a (public) bar() method on it, then it shouldn't make sense for Child to have it either. If it does make sense for Child to have a bar method on it, then Child isn't really a Parent, is it?
Maybe bar should be a method in some other class.
First we need to know why compiler is complaining !! You will never come to know the reason if anybody tell you the fix. First understand the reason.
You are getting the error during compilation. vTable and vPtr does not come into picture during early binding. It comes into picture in late binding. Base class does not have bar method, so compiler is complaining you that the method called by base class in unknown. So you need to typecast it to derived class pointer so that early binding gets passed. I hope my understand about the problem is correct. Correct me if I am wrong.
In an existing project, I am to inherit a Controller class (MVC) declared as Singleton so as to define my own treatment. How to appropriately derive this Singleton class?
First, I expand on context and need for this inheritance.
The application that I am added to the existing software wants to use a MVC module that performs almost same task as the one I am willing to perform. It is using the same methods up to signature and slight modifications. Rewriting my own MVC module would definitively be duplication of code. The existing module is intrinsically oriented towards its application to another part of the software, and I cannot simply use the same module. But is written as a Model-View-Controller pattern where Controller is Singleton. I derived View already.
Second, I have doubt that I can classicaly derive Singleton class.
Calling constructor from inherited class would simply call getinstance() for parent class and fail to return an object from derived class (?).
Third, it's how I see some way to deal with. Please comment/help me improve!
I copy the whole Singleton class in a class I could call AbstractController. I derive this class twice. The first child is singleton and adopts the whole treatment of parent class. The second child is the Controller for my part of the application, with own redefined treatment.
Thanks!
Truth is, singletons and inheritance do not play well together.
Yeah, yeah, the Singleton lovers and GoF cult will be all over me for this, saying "well, if you make your constructor protected..." and "you don't have to have a getInstance method on the class, you can put it...", but they're just proving my point. Singletons have to jump through a number of hoops in order to be both a singleton and a base class.
But just to answer the question, say we have a singleton base class. It can even to some degree enforce its singleness through inheritance. (The constructor does one of the few things that can work when it can no longer be private: it throws an exception if another Base already exists.) Say we also have a class Derived that inherits from Base. Since we're allowing inheritance, let's also say there can be any number of other subclasses of Base, that may or may not inherit from Derived.
But there's a problem -- the very one you're either already running into, or will soon. If we call Base::getInstance without having constructed an object already, we'll get a null pointer. We'd like to get back whatever singleton object exists (it may be a Base, and/or a Derived, and/or an Other). But it's hard to do so and still follow all the rules, cause there are only a couple of ways to do so -- and all of them have some drawbacks.
We could just create a Base and return it. Screw Derived and Other. End result: Base::getInstance() always returns exactly a Base. The child classes never get to play. Kinda defeats the purpose, IMO.
We could put a getInstance of our own in our derived class, and have the caller say Derived::getInstance() if they specifically want a Derived. This significantly increases coupling (because a caller now has to know to specifically request a Derived, and ends up tying itself to that implementation).
We could do a variant of that last one -- but instead of getting the instance, the function just creates one. (While we're at it, let's rename the function to initInstance, since we don't particularly care what it gets -- we're just calling it so that it creates a new Derived and sets that as the One True Instance.)
So (barring any oddness unaccounted for yet), it works out kinda like this...
class Base {
static Base * theOneTrueInstance;
public:
static Base & getInstance() {
if (!theOneTrueInstance) initInstance();
return *theOneTrueInstance;
}
static void initInstance() { new Base; }
protected:
Base() {
if (theOneTrueInstance) throw std::logic_error("Instance already exists");
theOneTrueInstance = this;
}
virtual ~Base() { } // so random strangers can't delete me
};
Base* Base::theOneTrueInstance = 0;
class Derived : public Base {
public:
static void initInstance() {
new Derived; // Derived() calls Base(), which sets this as "the instance"
}
protected:
Derived() { } // so we can't be instantiated by outsiders
~Derived() { } // so random strangers can't delete me
};
And in your init code, you say Base::initInstance(); or Derived::initInstance();, depending on which type you want the singleton to be. You'll have to cast the return value from Base::getInstance() in order to use any Derived-specific functions, of course, but without casting you can use any functions defined by Base, including virtual functions overridden by Derived.
Note that this way of doing it also has a number of drawbacks of its own, though:
It puts most of the burden of enforcing singleness on the base class. If the base doesn't have this or similar functionality, and you can't change it, you're kinda screwed.
The base class can't take all of the responsibility, though -- each class needs to declare a protected destructor, or someone could come along and delete the one instance after casting it (in)appropriately, and the whole thing goes to hell. What's worse, this can't be enforced by the compiler.
Because we're using protected destructors to prevent some random schmuck from deleting our instance, unless the compiler's smarter than i fear it is, even the runtime won't be able to properly delete your instance when the program ends. Bye bye, RAII...hello "memory leak detected" warnings. (Of course the memory will eventually be reclaimed by any decent OS. But if the destructor doesn't run, you can't depend on it to do cleanup for you. You'll need to call a cleanup function of some sort before you exit, and that won't give you anywhere near the same assurances that RAII can give you.)
It exposes an initInstance method that, IMO, doesn't really belong in an API everyone can see. If you wanted, you could make initInstance private and let your init function be a friend, but then your class is making assumptions about code outside itself, and the coupling thing comes back into play.
Also note that the code above is not at all thread safe. If you need that, you're on your own.
Seriously, the less painful route is to forget trying to enforce singleness. The least complicated way to ensure that there's only one instance is to only create one. If you need to use it multiple places, consider dependency injection. (The non-framework version of that amounts to "pass the object to stuff that needs it". :P ) I went and designed the above stuff just to try and prove myself wrong about singletons and inheritance, and just reaffirmed to myself how evil the combination is. I wouldn't recommend ever actually doing it in real code.
I'm not sure I understand the situation you're dealing with fully, and whether or not it's possible or appropriate to derive from the singleton depends very much on how the singleton is implemented.
But since you mentioned "good practice" there's some general points that come to mind when reading the question:
Inheritance isn't usually the best tool to achieve code re-use. See: Prefer composition over inheritance?
Using singleton and "good practice" generally do not go together! See: What is so bad about singletons?
Hope that helps.
I recently had the similar need in my app... in any case here is my out of code implementation :
h.
class icProjectManagerHandler;
class icProjectManager : public bs::icBaseManager {
friend class icProjectManagerHandler;
protected:
icProjectManager();
public:
~icProjectManager();
template<typename t>
static t *PM() {
return dynamic_cast<t *>(icProjectManagerHandler::PMH()->mCurrentManager);
};
template<typename t>
static t *PMS() {
static icProjectManagerHandler pm;
return static_cast<t *>(icProjectManagerHandler::PMH()->mCurrentManager);
};
};
class icProjectManagerHandler {
friend class icProjectManager;
icProjectManager *mCurrentManager;
icProjectManagerHandler();
public:
~icProjectManagerHandler();
static icProjectManagerHandler *PMH();
inline void setProjectManager(icProjectManager *pm) {
if (mCurrentManager) { delete mCurrentManager; }
mCurrentManager = pm;
}
};
Cpp.
icProjectManagerHandler::icProjectManagerHandler() {
mCurrentManager = new icProjectManager();
}
icProjectManagerHandler::~icProjectManagerHandler() {
}
icProjectManagerHandler *icProjectManagerHandler::PMH() {
static icProjectManagerHandler pmh;
return &pmh;
}
icProjectManager::icProjectManager() {
}
icProjectManager::~icProjectManager() {
}
And example:
class icProjectX : public ic::project::icProjectManager {
public:
icProjectX() {};
~icProjectX() {};
};
int main(int argc, char *argv[]) {
auto pro = new icProjectX();
pro->setIcName("Hello");
ic::project::icProjectManagerHandler::PMH()->setProjectManager(pro);
qDebug() << "\n" << pro << "\n" << ic::project::icProjectManager::PMS<icProjectX>();
return 10;
}
The issue of this implementation is that you have to initialize your "singleton" class 1st or else you will get the default base class. But other than that... it should work?
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.