So Suppose I have a animal class managed by zoo class.
Animal is an abstract class to be derived by other real animal classes
class Animal{
public:
Animal();
virtual ~Animal() = 0;
//Various animal related functions
}
class Zoo{
public:
Zoo();
virtual ~Zoo();
virtual void updateAll();
//And various other functions dealing with animals
private:
vector<animal*> animals
}
Now say I want to create a bird_zoo, and I want to reuse most of the code
used in Zoo class and Animal class.
So I make bird class
class Bird : public Animal{
public:
Bird();
virtual ~Bird();
//all the various functions derived from Animal class
virtual void fly(); //New function that Animal didn't have
}
class Bird_Zoo : public Zoo{
public:
Bird_Zoo();
virtual ~Bird_Zoo();
//And various other functions dealing with animals, derived from Zoo
virtual void flyAll(); //New function that Zoo didn't have
private:
//vector<??????> birds
}
How do I have this Bird_Zoo function deal with the Birds it has?
If I stay with vector<Animal*> from the Zoo class, how can I call fly()?
Do I really have to cast it to Bird* every time?
Is there way to conceptually "overload" vector<Animal*> as vector<Bird*>,
so that all the old Zoo function will still work fine?
Thank you.
One other possibility would be to use templates.
class Zoo {
// ...
virtual void updateAll() = 0;
};
template <typename T,
typename = typename enable_if<is_base_of<Animal, T>::value>::type>
class ZooWithAVector : public AbstractZoo {
public:
virtual void updateAll() { /* ... */ }
// Various functions dealing with T-animals
private:
vector<T*> animals;
};
typedef ZooWithAVector<Animal> TypicalZoo;
class BirdZoo : public ZooWithAVector<Bird> {
virtual void flyAll() { /* work with the vector<Bird> */ }
};
I would advice you to not have a vector<animal*> member in Zoo. A base class (especially an abstract one) should only implement what is in common for all potential derived classes.
Instead you could have a General_Zoo extending Zoo class which could handle all types of animals. So General_Zoo would be a sibling class of Bird_Zoo.
Your design is faulty. Theoretically, you'd think that a Bird_Zoo is-a Zoo. And it is. But not the way you modeled it.
You see, in your design, a Zoo contains a collection of any kind of Animal, whereas a Bird_Zoo does not. So, if you chose to model it like this, a Bird_Zoo is no longer a Zoo.
You can either not use inheritance for this, or, what I would do, remove the vector<Animal*> from the base class.
Related
I'm sure I'm not the first one to ask this question, but I can not find any answer for it.
The thing I want is a base class from which multiple classes are inherited. The inherited classes all have some functions (with implementation) and variables in common and have some variables and functions (different functions for every derived class) of there own. The common members I would like to combine in the base class. The thing is the base class should really just be a base class and I don't want any instances to be made of the base class. How should I do this?
If the above description is not clear, maybe this makes it more clear: let's say I want a base class mammals and derived class such as human, ape, blue whale, etc. I want to create instances of the human, ape, blue whale, etc. but not of mammals.
I have read somewhere you could put the constructor as private, but I need a public constructor of the derived classes
Making the base class abstract is your solution.
If you don't want to make any base class method pure virtual then you can make the destructor pure virtual
#include <iostream>
using namespace std;
class IMammal //I for Interface
{
public:
virtual ~IMammal() = 0; //Makes the class abstract, Pure virtual destructor
};
IMammal::~IMammal() //Its necessary or ld will complain
{
cout << "In ~IMammal" << endl;
}
class Ape : IMammal
{
};
int main()
{
// IMammal m; // error: cannot declare variable ‘m’ to be of abstract type ‘IMammal’
Ape a;
}
Since every method is implemented in the base class, using a protected constructor will allow you to add extra member variables to the derived class without being able to construct the base. To make it even more obvious, I'd probably put the base class in a different namespace, so the caller gets a strong hint that they shouldn't even try to create one.
namespace detail
{
class Mammal
{
public:
void layEggs() { /*implementation*/ }
protected:
//Stop anyone creating a Mammal
//Can still be accessed by derived classes,
//and anyone that Mammal has declared a friend
Mammal(int age) : age_(age);
int age_;
};
}
class Dog : public detail::Mammal
{
public:
//Dog is still allowed to access Mammal constructor
Dog(int age, const std::string& name) :
Mammal(age), name_(name)
{}
protected:
std::string name_;
};
Edit: I originally answered without understand that every method was implemented in the base class
You can do this by making the class an abstract class. You do this by creating at least one function a pure virtual function.
class Mammal
{
public:
void layEggs()
{
//implemented in base
}
virtual std:string speak() = 0 //pure virtual, so class cannot be instantiated
};
class Dog : public Mammal
{
public:
virtual std::string speak()
{
return "woof";
}
};
Because Mammal contains a pure virtual function, a variable cannot be created from it. However, Dog has implemented all of the functions, so a variable can be created.
Mammal m; //will result in compiler error, because what would m.speak() do?
Dog d; //is allowed, because we know what d.speak() should do
I think the suggestion of Alan Birtles might indeed work. Check this question What are practical uses of a protected constructor?
All functions I would have in the base class have an implementation in the base class. Otherwise using a virtual function would indeed be an option as well. I checked this website https://www.geeksforgeeks.org/pure-virtual-functions-and-abstract-classes/ maybe this is useful for others.
I have a class(names as example):
class Animal
{
public:
// some virtual methods
};
There are also some sub-classes.
class Dog : public Animal
{
public:
Dog(Map&);
// methods - using m_Map
private:
Map& m_Map;
};
class Elephant : public Animal
{
public:
Elephant(Map&);
// methods - using m_Map
private:
Map& m_Map;
};
As you can see, when creating Dog and Elephant objects, Map reference must be provided, and these classes uses it. There are a lot of more similar sub classes of Animal(Dog, Elephant, Mouse, Cat, and more...) - all uses Map object.
All sub-classes of Animal uses Map object, I was thinking about if it would be good idea to add it to Animal class as protected member, for example:
class Animal
{
public:
Animal(Map&);
// some virtual methods
protected:
Map& m_Map;
};
class Dog : public Animal
{
public:
Dog(Map& map) : Animal(map);
// methods - using Animal::m_Map
};
class Elephant : public Animal
{
public:
Elephant(Map& map) : Animal(map);
// methods - using Animal::m_Map
};
However, Animal class will never use Map object, so it seems for me a bit not natural to store it here - for only sub-classes usage.
On the other hand, all sub-classes of Animal will use Map object - so it would be good to indicate it in Animal class. And also I have feeling that code is duplicated when I define it as member in all sub-classes.
What do you think about it? Should Map object be defined as member in all sub-classes, or only in Animal class?
It depends on the semantic links in between animals and maps.
Since you are in C++, then you can use multiple inheritance.
First, implement a MapWrapper class:
class MapWrapper {
private:
Map *theMap;
public:
...
};
and then construct your animals like this:
class Dog : public Animal, private MapWrapper {
};
Note that private inheritance is not generalization/specialization, just a trick to implement some kind of strong composition.
Another possibility is to introduce an intermediate class in between Animal and Dog. Animal is probably a pure abstract class or a contract, so it is probably not fair to modify it for pragmatic purposes. Just introduce an AnimalMap:
class AnimalMap : public Animal {
// everything for the map
};
class Dog : public AnimalMap {
};
If a variable or function is required for all derived types of a base type, then that variable or function should be a part of the base type. This is the very premise of inheritance - de-duplication of code in a logical and systematic manner.
You mentioned that you are struggling with the fact that an Animal object will never actually use a Map. Have you considered a design of your type hierarchy which involves Animal being an abstract class? This means that an Animal would never be instantiated. This makes sense conceptually in the given example - no animal is an animal alone; the category of animal encompasses many other, more specific concepts such as a dog or cat.
I would suggest that this implementation fits your example and resolves your philosophical conundrum.
The map object would be defined in animal class only.why because you are inherit animal class properties for all your sub classes.
it is a advantage , you can create object for animal class ,and you can access the map until you did not have any pure virtual methods in animal class
when it comes to memory size of an object,there is no difference where you are holding the map ,whether in a in a base class or derived class.the size of an derived object will be same only
class animal
{
public:
int animal_id;
int animal_age;
};
class dog :public animal
{
public:
int dog_type_id;
};
int main()
{
dog d1;
animal a1;
cout<<"sizeof d1:"<<sizeof(d1)<<endl;
cout<<"sizeof a1:"<<sizeof(a1)<<endl;
return 0;
}
Consider the following code:
class Human
{
virtual void Walk() = 0;
}
class Male : public Human
{
void Walk();
}
class Female : public Human
{
void Walk();
Human* GiveBirth();
}
int main()
{
vector<Human*> people;
people.push_back(new Female);
}
Let's say I want to call GiveBirth() from the base class pointer, I would have these options:
1- Cast the pointer to the derived type
people.push_back( dynamic_cast<Female*>(people[0])->GiveBirth() );
Reason why I don't use it:
I need to make my program in a way that all derived classes are unknown by the user/programmer (even if it's logical to say that such a method is female related).
2- Make GiveBirth() method virtual
Reason why I don't use it:
This method would now be visible to Male class, which is everything but logical.
3- Use the 'Curiously Recurring Template Pattern'
Reason why I don't use it:
I don't know. Maybe I'm wrong with the usage of this pattern, but I think I could not create a global pointer to instantiate my derived classes since the base class is a template and it needs to know the type at compile time.
Is there any other program structure that could do what I want to achieve?
Functions in the base class should not be aware of functions in their derived classes or their behavior unless of course that functionality is required by the base class and the base class in return declares them as virtual or pure virtual.
In other words, the base class doesn't depend on the derived class. Code that does this create a circular dependency which should be avoided at all cost.
This means that you should declare or implement all the functions in the base class. If implemented, have them return an error (or throw an exception) so a derived class can override them with a proper implementation.
These functions in the base class will be virtual or pure virtual (preferred).
Example:
class Human
{
virtual void Walk() = 0;
Human* GiveBirth() = 0;
}
class Male : public Human
{
void Walk();
Human* GiveBirth() { return NULL; }
}
class Female : public Human
{
void Walk();
Human* GiveBirth();
}
I am fairly new to C++, but i have ran into an issue which i cannot seem to resolve.
I will use cars to illustrate the problem, just to make things easier.
Okay so lets say that i have a base class Car, and i have different brands that are inheriting from that class. Like so:
class Car
{
public:
Car();
};
class Ford: public Car
{
public:
Ford();
void drive();
void park();
};
The whole idea is to put all these different cars together in single a vector of the type Car. Like so:
vector<Car*> cars;
cars.push_back(new Ford());
cars.back()->drive(); //this won't work
How can i call the derived function on the base class instance? Note that i want to place these all in a single vector. The reason behind this is because i only want to use the last derived car class instance that has been added.(In this case the derived car class is ford). Also note that all car classes will have the same functions.
If these functions are truly common to all the derived classes, then you have a common interface, so you should express this via the base class. To do so, you declare these functions as pure-virtual:
class Car {
public:
virtual void drive() = 0; // Pure-virtual function
};
class Ford : public Car {
public:
virtual void drive() { std::cout << "driving Ford\n"; }
};
...
vector<Car*> cars;
cars.push_back(new Ford());
cars.back()->drive(); //this will work
[On a side note, it's generally considered poor practice to have a vector of raw pointers, because it makes memory management tricky. You should consider using smart pointers.]
You have two options: either put a virtual drive() method in your Car definition, or cast the Car pointers to Ford pointers. Chances are you'll want to do the first.
class Car
{
public:
Car();
virtual void drive() { // default implementation}
};
Now you can drive() your Car! You can also make drive() a pure virtual function, like so:
class Car
{
public:
Car();
virtual void drive() = 0;
};
This basically means that there is no default implementation for drive(): it MUST be reimplemented in a subclass. The second way I mentioned, which, again, you probably don't want, but should be included for completeness, is to cast the pointer:
static_cast<Ford*>(cars.back())->drive();
This only works if you know beforehand that the Car is a Ford, however, and isn't much use in this scenario. You could also look into dynamic_cast.
If all Car classes have the same functions then declare them as pure virtual in the base class Car:
class Car
{
public:
Car();
virtual ~Car();
virtual void drive() = 0;
virtual void park() = 0;
};
This will allow the example code that uses vector to work as posted.
May be if possible you can define base class as
class Car
{
public:
Car();
virtual void drive();
};
You have to define the interface like:
class Car{
public:
Car();
virtual void moveForward(unsigned int speed) = 0;
virtual void moveBack(unsigned int speed) = 0;
//...
virtual ~Car();
};
Don't forget to make the destructor virtual.
After that you just need to implement these methods in your child classes, and call them after.
Also in vector you could use the shared_ptr or just pass the instances directly.
You must put a virtual function.
A virtual function in the base class.
A virtual function can be implemented in the sub class, so you can specialize the behaviour of the drive() for example.
You can find a faq (or tutorial) about virtual functions here:
http://www.parashift.com/c++-faq-lite/virtual-functions.html
I have the following hierarchy of classes
class classOne
{
virtual void abstractMethod() = 0;
};
class classTwo : public classOne
{
};
class classThree : public classTwo
{
};
All classOne, classTwo and classThree are abstract classes, and I have another class that is defining the pure virtual methods
class classNonAbstract : public classThree
{
void abstractMethod();
// Couple of new methods
void doIt();
void doItToo();
};
And right now I need it differently...I need it like
class classNonAbstractOne : public classOne
{
void abstractMethod();
// Couple of new methods
void doIt();
void doItToo();
};
class classNonAbstractTwo : public classTwo
{
void abstractMethod();
// Couple of new methods
void doIt();
void doItToo();
};
and
class classNonAbstractThree : public classThree
{
void abstractMethod();
// Couple of new methods
void doIt();
void doItToo();
};
But all the nonAbstract classes have the same new methods, with the same code...and I would like to avoid copying all the methods and it's code to every nonAbstract class. How could I accomplish that?
Hopefully it's understandable...
template<class Base>
struct Concrete : Base {
void abstractMethod();
void doIt() {
// example of accessing inherited members:
int n = Base::data_member; // or this->data_member
n = Base::method(); // non-virtual dispatch
n = this->method(); // virtual dispatch
// since Base is a template parameter, 'data_member' and 'method' are
// dependent names and using them unqualified will not properly find
// them
}
void doItToo();
};
typedef Concrete<classOne> classNonAbstractOne; // if desired, for convenience
Make sure to give your abstract base classes either a virtual public destructor or make the destructor protected (then it doesn't have to be virtual, but still can be).
Because the template must be parsed with names looked up without yet knowing exactly what Base will be, you need to either use Base::member or this->member to access inherited members.
I usually try to avoid inheritance if possible (except for pure abstract classes which define pure interfaces) because it creates a tight coupling. In many cases composition is the better alternative.
Also, things tend to get messy with complex inheritance structures. It's not easy to say from your description what's the best in this particular case. Just pointing this out as a rule of thumb.