Interacting classes - organizing code - c++

I have some problem with organizing classes properly.
Suppose, I have some class ABase. When I want to create some different (more particular) abstraction of this class (denote it AParticular), I can use inheritance or just composition. Then it is easy to treat AParticular as ABase: in case of inheritance it is made automatically, in case of composition I can create some const ABase& AParticular::GetABasePart() method. By this I avoid code duplication and get polymorphic features.
But, when I have two or more classes that interact with each other, I have some problems to create analogues of these classes in a more particular abstraction.
For example, suppose, I have two classes Car and Station. Station has some public methods to maintain cars:
class Car {
...
}
class Station {
...
void AddCarToPlaceNumberN(const Car& car, int place_number) {
// adds car to some_container<Car>.
}
Car* GetMutableCarPointer(int place_number) {
// gets mutable pointer from some_container<Car>.
}
...
some_container<Car> cars;
}
Now, I want to create Truck and TruckStation classes: they are pretty similar to Car and Station classes and have minor changes. To understand problem it is sufficient to think as they do absolutely the same as Car and Station classes, but their methods have a bit other name (i.e. TruckStation::AddTruckToPlaceNumberN instead of Station::AddCarToPlaceNumberN)
How to organize the code of new classes to provide these features?
No code duplication, I want to use the already created Car and Station class methods.
Fast conversion Truck& -> Car&, TruckStation& -> Station& (Not necessary inheritance, composition is suitable also), since I want sometimes to treat Truck as Car and TruckStation as Station.
All interaction methods in level Car-Station should be realized in a new level Truck-TruckStation.
The main problem is the 3d item. Let's consider two interaction methods:
1) It is ok with this method:
// If we use inheritance in creating Truck and TruckStation, then we just run
void TruckStation::AddTruckToPlaceNumberN(const Truck& car, int place_number) {
AddCarToPlaceNumberN(car, place_number)
}
// If we use composition, then it is appropriate to run sth like that:
void TruckStation::AddTruckToPlaceNumberN(const Truck& car, int place_number) {
station_.AddCarToPlaceNumberN(car.GetCarPart(), place_number);
}
2) But I don't know how to implement the analogue of Station::GetMutableCarPointer():
// For example, if TruckStation was inherited from Station, then suppose:
Truck* TruckStation::GetMutableTruckPointer() {
Car* car = GetMutableCarPointer();
// Ups! I need to return Truck*, not Car*.
}
Repeat the question: how can I implement these classes to provide:
no code duplication.
Possibility to treat new classes as their higher level abstractions.
Implementation methods such as TruckStation::GetMutableTruckPointer() that correspond to Station::GetMutableCarPointer().
Tnx!

Getting specific to your code. I would do it this way.
Base class Vehicle extended by specific classes for Car and Truck.
Class Station with methods
void Station::AddVehicleToPlaceNumberN(const Vehicle& vehicle, int placeNumber)
Vehicle* Station::GetMutableVehiclePointer()
Reasons behind the design/class organization.
1. Use inheritance only when there is a need of different implementations. If different implementations of an inherited method do the same thing (like in case of AddVehicleToPlaceNumberN) then there is no need for separating the implementations.
2. Use of generic method name always helps in simplifying the code. The methods can be overloaded (passed with different number and type of parameters) to get a specific thing done.

The lazy way is to make the station use a generic type T so that; (Bear with me, I'm not completely clear with the C++ inheritance syntax, but the principle applies)
template<typename T>
class Station<T>:CarStation
{
void Station<T>::StatAddCarToPlaceNumberN(const T& car, int place_number)
{
// adds car to some_container<T>.
}
T * Station<T>::GetMutableCarPointer(int place_number)
{
// gets mutable pointer from some_container<Car>.
return dynamic_cast<T>(car);
}
}
And have an abstract superclass Station that implements a function to return a base pointer, say
class CarStation
{
//...
some_container<Car> cars;
virtual Car * CarStation::GetMutableCarBasePointer(int place_number) = 0;
}
Car * CarStation::GetMutableCarBasePointer(int place_number)
{
//gets mutable pointer to base class from some_container<T>
}
Now, if you want, you can create a new class TruckStation (This I am uncertain of in C++, again, I call principle)
class TruckStation : Station<Truck>
{
//...
}
or just go with Station<Truck>

Related

Fix a large class using inheritance

It seems to me that my class is too big and complicated, I would like to reduce it. Can I use inheritance in this way, given that I created the InitCar class only to inherit it and am not going to use objects of this class explicitly.
Before refactoring. People and License are not my own classes, I cannot change them.
class Car
{
public:
void Move();
void SpeedUp();
void SpeedDw();
//More other
private:
int speed = 0;
std::string name;
int id = 0;
People owner; // not my own class
License license; // not my own class
void InitCarFromConfig()
{
//Here I read the data from the file
}
void InitOwner()
{
//Here I init the People owner
}
void InitInspection()3
{
//Here I init the License license
}
};
After refactoring
class InitCar
{
protected:
std::string name;
int id = 0;
People owner; // not my own class
License license; // not my own class
void InitCarFromConfig()
{
//Here I read the data from the file
}
void InitOwner()
{
//Here I init the People owner
}
void InitInspection()
{
//Here I init the License license
}
};
class Car : InitCar
{
public:
void Move()
{
InitOwner();
}
void SpeedUp();
void SpeedDw();
//More other
private:
int speed = 0;
};
Is this use of inheritance acceptable and are performance issues possible?
Although it is true that you can use inheritance to reduce the size of you classes and reduce code duplication for other classes (which can also inherit InitCar for similar base functionality), it is actually not a good idea.
Functionality-wise, it does work, it does reduce code duplication and class sizes. However, it is a bad design, because it uses inheritance wrong, and breaks concepts of "clean code".
When you create a class, you create an entity which represents something. Inheritance create relations between those entities. Saying that Car inherits InitCar is saying that Car is a sort of InitCar, which logically makes no sense, because InitCar is just a helper class.
You can solve this if the base type was an actual entity, like Vehicle, and you had multiple vehicles. However, your InitClass is specifically intended to split you code, so it doesn't actually make a Vehicle, renaming it won't fix the design.
Composition over inheritance
A well known concept in "clean code", saying that it is better to hold functionality helping classes as variables in the class, rather then inherit from a base class. It is both more flexible for switching implementations, and does not abuse the purpose of inheritance:
class Car {
public:
void Move();
void SpeedUp();
void SpeedDw();
//More other
private:
int speed = 0;
std::string name;
int id = 0;
People owner;
License license;
HelperClass helper; // new class for initing..
void InitCarFromConfig()
{
//data = helper.InitCarFromConfig();
}
void InitOwner()
{
//owner = helper.InitOwnerForCar(param);
}
void InitInspection()
{
//data = helper.InitInspection(param);
}
};
Now we simply delegate our calls to the helper class (whose name is just a stub, you should have a name matching what it does, or maybe several classes). So we do save some space, we don't abuse inheritance and typing, and we now actually have flexibility in implementation, since now we can replace the instance of helper and get a new logic.
How do we init helper? Usually receiving via the constructor is the best idea. But you can create inside the class if you really want to.
Best design for your case
But is it the best design here?! No actually. Because the real problem in the class is the existence of the Init_ methods within the class.
When creating a class, it is important that when the constructor finishes running, the class is completely initialized. When it is not, we create several problems:
Risk a chance that the class is used, and some properties/methods are not complete for use, causing errors
Complexity of the class is increased, making maintenance harder (which is what you pointed as the issue for you).
Limits the users of the class from flexibility in its creation, thus limiting the design options for using the class. Creating tests for example, will be a nightmare.
Very risk for multithreading use, and harder to handle
Instead than, what we can do is receive all the data we need to operate from the constructor, and simply store it:
public:
Car(std::string name, id, People owner, License license);
Now comes another issue: what if it is difficult to perform initialization. After all you have 3 methods for initializing your class, so could be not easy for users. This is were the Factory design pattern comes in. We will create a class, named CarFactory (or so) and use it to create our classes. Within it, it will have all the logic to init the class data:
class CarFactory {
public:
Car* CreateCar(params_from_user) {
// init data
return new Car(data);
}
};
What did we accomplish with this:
We made Car smaller and less complex
We allowed users more options about how to use Car
We maintained the Init option from earlier, to help create Car
Our code is a lot easier to look at and maintain because it is separated logically, and classes are small
Car is fully initialized after constructor call

How would you access derived methods using a base pointer ?

I have seen several posts on this topic, but did not find the kind of solution I am looking for. So sorry at the outset for yet another duplicate. But I want to know what you experts will do faced with a situation as given below ?
class Vehicle // A base class
{
public:
static Vehicle* CreateInstance(const int createWhat)
{
switch(createWhat)
{
case 1:
return new Segway();
break;
case 2:
return new Car();
break;
}
}
};
Now I have a couple of derived classes ..
class Segway : public Vehicle // Segway is a vehicle
{
};
class Sensor
class FuelConsumptionInfo;
class Car : public Vehicle // Car is a vehicle
{
public:
std::list<Sensor>& GetSensorList()
{
return m_pListOfSensors;
}
bool CompareThisCarAgainstOthers(std::list<Vehicle*>& vehicles) const
{
bool isMostEfficientCar = false;
std::list<Vehicle*>::iterator iterVal = vehicles.begin();
while(iterVal != vehicles.end())
{
// 1. Get the list of sensors of this car and compare against the sensors of this car ...
// 2. Get the fuel consumption information and compare against the fuel efficiency of this car ...
}
return isMostEfficientCar;
}
private:
std::list<Sensor*> m_pListOfSensors;
FuelConsumptionInfo* m_FuelEfficiency;
};
And finally I have my favourite car and a set of other cars, and I want to compare my car against them.
int main()
{
std::list<Vehicle*> listOfOtherCars;
Vehicle* pMyFavCar = Vehicle::CreateInstance(2);
listOfOtherCars.push_back(Vehicle::CreateInstance(2));
listOfOtherCars.push_back(Vehicle::CreateInstance(2));
listOfOtherCars.push_back(Vehicle::CreateInstance(2));
listOfOtherCars.push_back(Vehicle::CreateInstance(2));
// How can I invoke the CompareThisCarAgainstOthers without:
// 1. Introducing any base class empty functions ..
// 2. Without using static/dynamic casting to convert the base pointer to a derived class pointer ...
}
As already mentioned in the comments, I want to invoke the CampareThisCarAgainstOthers, but I do not want to cast the base class pointer, nor do I want to introduce any virtual functions in the base class which I think defies the whole logic of having a base class. Even introducing empty virtual base functions will not help because GetSensorList returns a reference to the list.
I will be very thankful to your answers.
The only way to access a child method using a base pointer is by casting the base pointer to a child pointer. This has bad side effects (search the internet for "C++ object slicing").
One issue is that you don't know what kind of child / object the base pointer is pointing to. You could cast the pointer to a wrong child method. Example: a pointer to a Cruise Ship is passed to a function taking a pointer to vehicle. What happens when inside the function, the pointer is cast to a Bicycle type. Clearly, not the same vehicle.
All you can safely access with a pointer to a base class is the public methods and members of the base class. No more, no less.
For example, given a base class of Car and some child classes such as Model_T, Tesla, Hybrid and Mustang, and a pointer to a Car instance, you don't know what kind of car the child is. A Model_T is different than an electric Tesla. A Mustang with a gasoline engine is different than a Hybrid with both electric and gasoline engines.
If you want to access functionality using a base class pointer, put the functionality into the base class as an abstract function. The Car class could have a method virtual bool has_electric_engine(void) const = 0;. The Model_T and Mustang would return false.
Please don't make virtual equality methods into a base class because the code will be comparing attributes, but you really want to compare types. In the example, the Mustang car does not have all the same attributes as the Model_T. Usually, if you need to compare types, your design is flawed.

Class Design for Classes with few differences

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.

Two related class hierarchies - overriding virtual functions

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.

C++ - Overuse of virtual methods?

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.