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
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.
Let's assume you have an base class for the different states of a State Machine that has methods for different inputs like mouse, keyboard, joystick, etc. Now not every derived state is going to use all possible types of inputs. If the base class methods are pure virtual every derived state class needs to always implement every single one of them. To avoid this i declared them with an empty body in the base class and just override the ones that are used by the particular derived class. In case the class doesn't use a certain input type the empty base class method get's called. I am storing the currentState in a base class pointer and just feed it with the input without having to know which particular derived state it actually is to avoid unnessecary casts.
class Base
{
public:
virtual void keyboardInput() {}
virtual void mouseInput() {}
};
class Derived : public Base
{
public:
void keyboardInput()
{
// do something
}
// Derived doesnt use mouseInput so it doesn't implement it
};
void foo(Base& base)
{
base.keyboardInput();
base.mouseInput();
}
int main()
{
Derived der;
foo(der);
}
Is this considered a good practice?
Your question is opinion based, but I'd rather follow this approach to use an interface:
struct IBase {
virtual void keyboardInput() = 0;
virtual void mouseInput() = 0;
virtual ~IBase() {}
};
class Base : public IBase {
public:
virtual void keyboardInput() override {}
virtual void mouseInput() override {}
};
class Derived : public Base {
public:
void keyboardInput() override {
// do something
}
// Derived doesnt use mouseInput so it doesn't implement it
};
int main() {
std::unique_ptr<IBase> foo = new Derived();
foo->keyboardInput();
foo->mouseInput();
return 0;
}
Some arguments why that's better practice added from the comments:
The idea is that interface should contain as little assertions as possible, making it less likely to change, making it more dependable for those who inherit from it. Implementing the methods, albeit empty, is already an assertion, however small.
It would be less pain for refactorings coming later, which introduce more interfaces with multiple inheritance.
It really depends on what you want from the methods. When declaring an interface, usually the methods are left pure virtual because they are required to be implemented for the class to work at all. Marking them pure virtual signals "You have to implement this.".
However, sometimes there are methods that may do nothing and it's valid for all possible implementations for them to do nothing. It is not very common, but it is possible.
I don't think that your interface is the case though, and you should follow #πάντα ῥεῖ's answer. Or do it through multiple inheritance:
class MouseInput {
public:
virtual void mouseInput() = 0;
}
class KeyboardInput {
public:
virtual void keyboardInput() = 0;
}
class Derived : public KeyboardInput
{
public:
virtual void keyboardInput() override
{
// do something
}
};
class AllInput : public KeyboardInput, public MouseInput
{
public:
virtual void keyboardInput() override
{
// do something
}
virtual void mouseInput() override
{
// do something
}
};
That has the benefit that you can have methods that explicitly say that they work with one kind of input:
void doSomethingMouseIsh(MouseInput* input);
The disadvantage is that methods that combine mouse and keyboard input get weird unless you have InterfaceAllInput as interface and use it for all "all input methods"
Final note: as long as you try to write clean code, considering each use case is more important than some best practices.
If you going to be strict about it this does violate ISP (https://en.wikipedia.org/wiki/Interface_segregation_principle) as your forcing a subclass to depend on a method it doesn't use - but generally its not too bad in practice if the alternative adds more complexity.
I have an abstract base class. Suppose, I want the derived class to also be abstract and leave the responsibility of implementation of the pure virtual functions to a further lower class. What is the best way of doing it?
class Animal {
public:
virtual void makeNoise() = 0;
};
class Dog : public Animal {
};
Is it better to leave it blank like this, or should I do:
class Dog : public Animal {
public:
virtual void makeNoise() = 0;
};
Or how about ignoring the virtual keyword and:
class Dog : public Animal {
public:
void makeNoise() = 0;
};
What is the most suitable way of doing it?
There is no functional difference between the different options (as you don't change the accessibility), but
I'd prefer option one, as it avoids code duplication.
Option 3 is the worst possibility, because - although it is obvious that a pure virtual function (indicated by =0) is virtual - it is less consistent with the declaration of other (pure) virtual functions introduced in Dog.
I'd only revert to option 2 if
Dog is part of a library that you distribute to others
It introduces new pure virtual functions itself.
Animal itself is not supposed to be further used by the "typical user" directly
That way, a client that derives from Dog has all necessary information about which functions he has to implement in one place.
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();
}
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.