C++ passing family of objects to class [duplicate] - c++

This question already has an answer here:
can dynamic binding happen without using pointer and using regular object in c++
(1 answer)
Closed 4 months ago.
I am trying to find a way to create a generic "car" class, with children that overload the parent's methods. Subsequently, I would like to have a user class that has as a member any class in the "car" family. Is there a way to achieve the desired functionality? Thank you!
The pseudocode below shows what my intial attempt was, but the compiler obviously complains that User wants a Car object, not a Toyota.
class Car
{
public:
Car();
void method1();
};
class Toyota : public Car
{
public:
Toyota();
void method1();
};
class Lada : public Car
{
public:
Lada();
void method1();
};
class User
{
public:
User();
Car car;
};
int main()
{
User user;
Toyota toyota;
user.car = toyota;
}

There are several ways to achieve this. One approach is to use pointers or references which allow you to use runtime polymorphism. A pointer or reference to a Car can also point to any object of a class derived from Car. However to get true polymorphism you need to declare the methods virtual. Also you really should delcare a virtual ~Car() = default destructor:
struct Car {
virtual ~Car() = default; // virtual destructor is important if you
// hold owning references or pointers that
// you want to use to destroy the object
// (like for example std::unique_ptr)
virtual void method1(); // declare this virtual if you want
// polymorphic behaviour on method1
};
struct Toyota : public Car {
void method1() override; // no need to declare this virtual because
// it is already virtual in base class.
// the 'override' would warn you if there was
// no 'virtual method1' in the base class
};
// ...
Toyota toyota;
Car& car_ref = toyota;
Car* car_ptr = &toyota;
car_ref.method1(); // calls Toyota::method1()
car_ptr->method1(); // calls Toyota::method1()
If using references or pointers you should keep in mind that they are non-owning. You must ensure, that the object that is referenced exists if you dereference the pointer or reference.
Car& f() {
Toyota toyota;
Car& car_ref = toyota;
return car_ref; // badooomz: return of reference to toyota
// that is going to be destroyed at the end
// of scope. You do not want this
}
An easy way to couple ownership to a pointer is to use std::unique_ptr:
std::unique_ptr<Car> f() {
auto toyota = std::make_unique<Toyota>();
return std::move(toyota);
}
An entirely different way to achieve your goal is to use static polymorphism (or duck typing) through std::variant:
struct Car {
void method1(); // no virtual functions needed
};
struct Toyota { // note: no inheritance here
void method1();
};
// ...
Toyota toyota;
// store a toyota in the variant
std::variant<Car, Toyota /*,...*/> car = toyota;
// call Toyota::method1()
std::visit([](auto&& car_like){ car_like.method1(); }, car);
Note that there is no relationship at all between Car and Toyota in this example. You could store any object in the variant, for which obj.method1() is a valid function call. That is why this kind of static polymorphism is called duck typing - anything that looks like a duck is treated like a duck. Note that when using std::variant you store a copy of the object and not a reference in the variant. Thus it is safe to return the variant from a function even if the original object is destroyed when leaving the function scope.

i think you should use virtual functions inside car and a reference pointer on assigning class toyota to car, the code i written below is working good.
#include <iostream>
using std::cout;
class Car
{
public:
Car(){cout << "A car";};
virtual void method1(){cout << "from car";};
};
class Toyota : public Car
{
public:
Toyota(){cout << "A toyota";};
void method1() {cout << "from toyota";};
};
class Lada : public Car
{
public:
Lada(){cout << "A Lada";};
void method1() {cout << "from lada";};
};
class User
{
public:
User(){cout << "A user";};
Car *car;
};
int main()
{
User *user = new User();
Toyota toyota;
user->car = &toyota;
delete user;
/***
if you dont need pointers then
User user;
Toyota toyota;
user.car = &toyota;
/**
}

Related

How to access derived class member function using Base class function?

I am trying to design a parking system (Low-level Design )
Some classes behave like this.
class Vehicle
{
public:
int entryTime;
int exitTime;
virtual void leaveParking(Vehicle*);
virtual int getChargePerHr();
//virtual void getChargePerHr() = 0;
Vehicle() {}
};
class Car : public Vehicle
{
private :
int chargePerHr = 30;
public:
void leaveParking(Vehicle*);
int getChargePerHr();
Car(){}
};
class Bike : public Vehicle
{
private :
int chargePerHr = 10;
public:
void leaveParking(Vehicle*);
int getChargePerHr();
Bike(){}
}
void Vehicle ::leaveParking(Vehicle* v)
{
int pay = v-> // Here expecting Car class member function getChargePerHr() should come
//so that I can access private member chargePerHr of car class.
// But I am not able to access the Car class member function here.
}
int main()
{
Car c1; // assume Car c1 has already parked.
Vehicle v;
Vehicle* vptr = new Vehicle();
vptr = new Car();
c1.leaveParking(vptr); // Car c1 wants to leave the parking place
}
I want to access getChargePerHr() of Car class using Base class Vehicle member function.
I tried with pure virtual function but still could not make it.
Could anyone help me?
Problem
Here:
void Vehicle::leaveParking(Vehicle* v)
{
...
}
You're not able to access Car::getChargePerHr() because v is a Vehicle not a Car.
Clearly you're attempting to achieve polymorphism since it appears you want derived classes of Vehicle to perform the same actions when they leave parking.
Solution
Declare Vehicle::getChargePerHr() as pure virtual (or virtual if you want a default implementation)
Provide implementations of getChargePerHr() in your derived classes
Implement Vehicle::leaveParking() using just the methods you've defined in Vehicle
At runtime, the virtual table will resolve overrides and call the correct derived implementation.
Other Issues
You are inheriting from Vehicle without declaring its destructor virtual. This means if any child classes need to perform clean-up, their destructors won't be called.
You're missing a semicolon after the Bike class declaration.
If every Vehicle does the same thing when leaving parking, it doesn't make sense to have leaveParking() be virtual—you make a member function virtual if you want it to be able to be overridden by child classes.
Vehicle::leaveParking() should probably not be taking another Vehicle as a parameter. The function acts on the vehicle itself, not on a different one.
If your constructor is empty, it's better to leave it out of the class declaration since it can confuse others who might read your code.
And many more issues. I suggest you take aalimian's advice to read up on C/C++. Your code shows many misunderstandings.
Code
Putting everything together, here's an example:
class Vehicle
{
public:
int entryTime;
int exitTime;
virtual ~Vehicle() = default;
void leaveParking();
virtual int getChargePerHr() = 0;
};
void Vehicle::leaveParking()
{
// This will call a derived class's implementation
int pay = getChargePerHr();
// Do more vehicle stuff
}
class Car : public Vehicle
{
private:
int chargePerHr = 30;
public:
int getChargePerHr() override;
};
int Car::getChargePerHr()
{
return chargePerHr;
}
class Bike : public Vehicle
{
private:
int chargePerHr = 10;
public:
int getChargePerHr() override;
};
int Bike::getChargePerHr()
{
return chargePerHr;
}
You can see this in action here.

Storing polymorphic types in one data structure

You have an animal Shelter. Shelter can store variable number of Animals. You put many Animals (Dogs and Cats) into the shelter.
Then you tell the employee to randomly select and bring you few Animals. You don't know what type of an Animal he selected.
You tell them to Speak. Some of them goes "bark", some goes "meow".
Important! Dogs can fetch and Cats can't.
If you know for sure you've selected a Dog it should be able to fetch right away (without upcasting from Animal to Dog for example)
How to implement this kind of logic? (preferably without boost::any)
Here is a partially working example: http://ideone.com/kR4788
#include <iostream>
#include <map>
using namespace std;
class Animal {};
class Shelter {
private:
std::map<int, Animal*> animals;
public:
void Add(Animal* animal) {
animals[animals.size()] = animal;
};
Animal* Select(int index) {
return animals[index];
}
};
class Dog: public Animal {
public:
void Speak() { cout << "bark" << endl; }
void Fetch() {}
};
class Cat: public Animal {
public:
void Speak() { cout << "meow" << endl; }
};
Shelter shelter;
int main() {
shelter.Add(new Cat());
shelter.Add(new Dog());
// I'd like to make it work like this
//
// shelter.Select(0)->Speak(); /* meow */
// shelter.Select(1)->Speak(); /* bark */
//
// Like below but without upcasting to given animal
((Cat*) shelter.Select(0))->Speak();
((Dog*) shelter.Select(1))->Speak();
// I know under index 1 is a Dog so it can fetch!
//
// shelter.Select(1)->Fetch(); /* no segfault */
//
// Like below but without upcasting to given animal
((Dog*) shelter.Select(1))->Fetch();
return 0;
}
Edit:
You can try to use a dynamic_cast to cast your Animal object into a Dog and then call the fetch method:
Dog *foo = dynamic_cast<Dog*>(shelter.Select(1));
if (foo) {
foo->Fetch();
}
If the dynamic_cast fails, it will return null so make sure to check if the object is not null before using it. For more information on dynamic_cast, check here.
You can add a virtual function to your Animal interface:
class Animal {
public:
virtual void speak();
};
Also, on an unrelated note, your speak method doesn't seem to be modifying the object so you should consider putting them as const:
class Animal {
public:
virtual void speak() const;
};
You can find more information on const-correctness here.
As Aliou noticed speak should be declared virtual in Animal, otherwise the hierarchy is rather useless, or, in other words, there is no polymorphism.
Testing if an Animal is a Dog (and upcasting at the same time) with dynamic_cast<Dog*> is an option to consider. Not pretty, but it works.
Dog *dog = dynamic_cast<Dog*> shelter.Select(1);
if (dog) dog->Fetch();
(dynamic_cast to a pointer never throws, as others suggested...)
Another solution is to define virtual Fetch in Animal, perhaps as a NOP ({}), so you don't have to define it in animals which don't fetch.
As per request I post my comment as an answer. The full source is in Ideone:
In class Animal:
class Animal {
public:
virtual void Speak() const = 0;
virtual void Fetch() const { cout << "This animal can't fetch" << endl;};
virtual ~Animal(){ }
};
The virtual destructor is needed to ensure that the correct destructor is called for objects that derive from the base class. Without the virtual destructor only the base class destructor would be called and not the destructor for the derived object.
In Dog:
void Fetch() const { cout << "fetch" << endl; }
And in main:
shelter.Select(0)->Speak();
shelter.Select(1)->Speak();
shelter.Select(0)->Fetch();
shelter.Select(1)->Fetch();
You didn't ask the employee to return only animals which could fetch, therefore you must check (cast) each animal can fetch.
The alternative is to add a dummy fetch function to animal, which doesn't do anything except for dogs.

Inheritance initialization in main function in C++ [duplicate]

This question already has answers here:
Polymorphism in C++
(7 answers)
Closed 9 years ago.
From past few weeks I am learning and experimenting inheritance and Polymorphism in C++.
Few syntax always confusing me to understand, mainly object calling from main function.
for eg:
#include <iostream.h>
using namespace std;
class Base
{
public:
Base(){ cout<<"Constructing Base";}
virtual ~Base(){ cout<<"Destroying Base";}
};
class Derive: public Base
{
public:
Derive(){ cout<<"Constructing Derive";}
~Derive(){ cout<<"Destroying Derive";}
};
void main()
{
Base *basePtr = new Derive();
delete basePtr;
}
Here is my question:
What actually happens when Base *basePtr = new Derive(); this syntax is called? and what are the advantages?
As per my knowledge I understood it calls derive class object and stores it in a pointer to base class object. Am I correct? If I am, why are we storing it in base class?
To clear my doubts I went through memory layout of class objects and disassembling, but it confuses me more.
Could anyone tell me how to understand this kind of syntax?
Public inheritance means that every object of the derived class IS at the same time an object of the base class (it provides all the interfaces the base class has). So, when you write:
Base *basePtr = new Derive();
new object of class Derive is created, than the pointer to it is assigned to basePtr and through basePtr you can access all the functionality Base class provides.
And if you then call any of Base class virtual functions like:
basePtr->callSomeVirtualFunction();
the function from the actual object class will be invoked, as it happens with the destructor in the end of your main function.
When you are using pointer to a base class object instead of pointer to a derived one, you are saying that you need only BASIC properties of this derived class.
Hmmm... Pointers are confusing at the beginning.
When you call Base *basePtr = new Derive();, you are creating a Derive object instance and just keeping a "bookmark" of where this object is, but with a Base pointer.
When you do that, the only accessible properties (without a cast) will be from Base class.
Why this is used? To abstract things. Imagine that you are coding something related to mugs, cups, glasses and jugs. Basically all types of those objects are make to store some kind of liquid. So I'll call the base class of LiquidContainer:
class LiquidContainer
{
//...
};
class Mug : public LiquidContainer
{
//...
};
class Glass : public LiquidContainer
{
//...
};
class Cup : public LiquidContainer
{
//...
};
class Jug : public LiquidContainer
{
//...
};
All the others are inherited from LiquidContainer, although the Jug, the Cup and the Mug could be created in a little more sophisticated inheritance tree.
Anyway, the intent of having a base class and using polymorphism is to avoid code replication and to abstract thins, allowing that all the LiquidContainer family be treated almost the same way.
Take by example a more complete class definition.
class LiquidContainer
{
public:
LiquidContainer(unsigned int capacity, unsigned int color) :
mCapacity(capacity),
mColor(color)
{
}
unsigned int getCapacity() { return mCapacity; }
unsigned int getColor() { return mColor; }
virtual char* name() = 0;
protected:
unsigned int mCapacity;
unsigned int mColor;
};
class Mug : public LiquidContainer
{
public:
Mug() :
LiquidContainer( 250, 0xFFFF0000 ) // 250 ml yellow mug!
{
}
virtual char* name() { return "Mug"; }
};
class Glass : public LiquidContainer
{
public:
Glass() :
LiquidContainer( 200, 0x000000FF ) // 200 ml transparent glass!
{
}
virtual char* name() { return "Glass"; }
};
class Cup : public LiquidContainer
{
public:
Cup() :
LiquidContainer( 50, 0xFFFFFF00 ) // 50 ml white cup!
{
}
virtual char* name() { return "Cup"; }
};
class Jug : public LiquidContainer
{
public:
Jug() :
LiquidContainer( 1500, 0x0000FF00 ) // 1.5 l blue Jug!
{
}
virtual char* name() { return "Jug"; }
};
With those class definitions you could do the following test:
#include <iostream>
#include <vector>
int main( int argc, char* argv[] )
{
std::vector< LiquidContainer* > things;
things.push_back( new Mug() );
things.push_back( new Cup() );
things.push_back( new Glass() );
things.push_back( new Jug() );
for ( auto container : things )
{
std::cout << "This is a '" << container->name() << "' with capacity of " << container->getCapacity() << "ml and color " << container->getColor() << std::endl;
}
return 0;
}
This little program outputs
This is a 'Mug' with capacity of 250ml and color 4294901760
This is a 'Cup' with capacity of 50ml and color 4294967040
This is a 'Glass' with capacity of 200ml and color 255
This is a 'Jug' with capacity of 1500ml and color 65280
I hope that this little exercise are enough to show you why the polymorphism is used.
That's called Polymorphism. It means that the object is a Derive as well as Base and can be used as both. For eg. If Dog is the subclass of Animal. Object of dog can be treated as Animal too. All dogs are animal, but not all animals are dog.
So you can call a dog an animal, that's why you can give the address of subclass object(Derive) to superclass pointer(Base). But it'll remain an object of subclass and will function like one. This is just to fool compiler into understanding that it's an object of Base.
Now the benefit is you can have a method which can accept object(or pointer in precise sense) of Base class, but can be passed any of it's subclass. The con here is you can only call methods which are in the base class and may or may not overridden in derive class.

Calling function from derived class through base class that is not overridden

in C++;
Is there a way of calling a function from a derived class through the base class
even when the function is not overridden? In other words, I'm using a base class in
order to have heterogeneous containers without boost; I want to call a member function
that is only specific to a derived class...
Example:
(I just made this code up so there's probably a syntax error but hopefully you get the gist)
class Vehicle
{
public:
virtual void do_vehicle_stuff();
// virtual void do_car_specific_stuff(); makes no sense here
}
class Car : public Vehicle
{
public:
void do_vehicle_stuff();
void do_car_specific_stuff();
}
Car a,b;
list<Vehicle> vehicle_list;
vehicle_list.push_back(a);
vehicle_list.push_back(b);
vehicle_list.front().do_car_specific_stuff();
error: 'Class Vehicle' has no member named 'do_car_specific_stuff()'
You are slicing your classes when you insert them into the list. In
C++ subtype polymorphism (the kind of polymorphism you are using) only
works through references or pointers but not values. When you insert
your carS into the list they are converted to VehicleS.
An example:
Car c;
std::vector<Vehicle> vs;
vs.push_back(c); // slicing happens
vs.front(); // not a car anymore, but just a vehicle,
// the Car-ness is lost through the copy operation
How do to it:
std::vector<std::unique_ptr<Vehicle>> vs;
vs.push_back(new Car());
vs.front(); // actually a Car
After you have resolved that fundamental flaw of your code, this might
help you:
Vehicle* vehiclep = new Car();
if(auto carp = dynamic_cast<Car*>(vehiclep)) {
carp->do_car_specific_stuff();
}
This is a rather costly operation and usually an indication of a
design smell, so you might want to rethink what you are doing.
Here's a more appropriate design:
struct Vehicle
{
virtual ~Vehicle() { }
void do_vehicle_stuff()
{
vehicle_impl();
}
private:
virtual void vehicle_impl() = 0;
};
struct Car : Vehicle
{
private:
virtual void vehicle_impl()
{
my_vehicle_stuff();
my_car_specific_stuff();
}
void my_vehicle_stuff() { /* what you had originally */ }
void my_car_specific_stuff() { /* car-only stuff */ }
};
std::list<std::unique_ptr<Vehicle>> vehicles;
vehicles.emplace_back(new Car);
vehicles.emplace_back(new Motorcycle);
vehicles.emplace_back(new Carriage);

Checking for derived class type

This is an example of a problem I have while designing an interface.
I have a class Animal and I have derived Cat, Dog and Lion from it. Now I have a function 'feedFood' which takes in the base class Animal as parameter. Based on the type of animal I should feed different food to the Animal.
So how do I check the type of the animal in the 'feedFood' function.
There are 3 methods I could think of
Adding a 'AnimalType' enum in the base class which is set to the right type in the derived class.
Add a virtual function in base class to return a string with animal type. In derived class return the proper string for the animal name.
Use typeid or dynamic_cast to check the type of the derived class in the 'feedFood' function.
Which is the best method or is there any other better approach for this?
You are currently saying this:
void feedFood(Animal &);
Cat myCat;
Dog myDog;
feedFood(myCat);
feedFood(myDog);
// Problem: How does feedFood() know what's going on?
To use polymorphism, make the feeding function a virtual member of Animal:
struct Animal
{
virtual void feedFood() = 0; // pure virtual or default behaviour, up to you
virtual ~Animal() { } // always provide virtual destructor!
/* ... */
};
struct Cat : public Animal
{
void feedFood() { /* Cat implementation */ }
/* ... */
};
// Usage:
// via reference
void feed(Animal & a) { a.feedFood(); }
// via pointer
Animal * b = new Bat;
b->feedFood();
Try this:
class Animal{};
class Dog: public Animal{};
class Cat: public Animal{};
class Lion: public Animal{};
void FeedFood(Dog& d)
{
cout << "Feeding the dog.\n";
return;
}
void FeedFood(Cat& c)
{
cout << "Feeding the cat.\n";
return;
}
void FeedFood(Lion& l)
{
cout << "Feeding the lion.\n";
}
void FeedFood(Animal& a)
{
cout << "Feeding an unknown animal.\n";
return;
}
With the above functions, the compiler will take care of feeding animals.
Sometimes, functionality may be better placed outside the class.
Okay, somewhat complicated, but resolves at compile time:
template <class _Derived>
class Animal
{};
class Dog: public Animal<Dog>
{
public:
void Feed()
{
cout<<"Feeding Dog...";
}
};
class Cat: public Animal<Cat>
{
public:
void Feed() { /* Feed Cat*/ }
};
And implement ONE template function:
template<class _AnimalType>
void FeedAnimal(_AnimalType& animal)
{
animal.Feed();
}
Create instance of any class, and call FeedAnimal:
Dog dog;
Cat cat;
FeedAnimal(dog);
FeedAnimal(cat);
If Feed is not implemented by derived-class, you may not get error, until you call Feed template function. Therefore, if Lion is implemented like:
class Lion : public Animal<Lion>
{};
You won't get any error that Feed is missing from class. As soon as you make call to FeedAnimal with Lion, you would get error that Lion is missing Feed method.
This is one of the hack to ensure that derived class implements Feed:
template <class _Derived>
class Animal
{
void (_Derived::*pDummy)();
public:
Animal()
{
pDummy = &_Derived::Feed;
}
};
Dirty, but works!
Not the animal gets food feeded, but it ates it. So add a virtual 'eat' method together with some FoodProvider on which the Animal can eat on.
Update:
So instead of an
void feed (const Food & food);
use
virtual void eatFrom (FoodProvider * provider);
That way you can also implement different food resources in your provider.