1

I have read that it is not good to overuse inheritance in C++. I have a simple example where I would like to know if it is good or bad to use it to initialize values in the base class constructor.

Let's say I have a class Animal :

class Animal{
protected :
Animal(std::string name, std::string category);
std::string m_name;
std::string m_category;
};

Is it good to create a specific class for each animal the application is going to use for example :

class Bear : public Animal{
public :
Bear():Animal("Bear", "Mammal"){
}
};

Of course that means that if I have 100 animals, I need 100 classes, and that feels awkward to my eyes. In this example, I am using inheritance only to initialize values, there won't be any specific virtual methods involved.

Thanks

4 Answers 4

3

Broadly speaking, the choice of whether to create derived classes or to just have data members on one class becomes a question of whether more classes actually help with the situation you're trying model/solve in the software.

For instance, an application that cares about how vehicles travel might have different classes for Car, Boat, Airplane, Helicopter, etc. On the other hand an application that only cares about the existence of vehicles (say it's for tracking what a business owns) might only need a single class for Vehicle in general.

As one rule of thumb, ask yourself if the derived classes are actually going to behave differently in any way, as far as what the rest of your program is concerned with. If yes, then derived classes may be what you want. If no, then probably not.

In your specific case, is there going to be any real difference between

Bear bear;

and

Animal bear("Bear", "Mammal");

If not, then a derived class of each type of Animal sounds excessive (100 derived classes sounds excessive in general) and you probably want to do something else depending on how you want to store the data. Perhaps making a list or map of Animal instances.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for your answer ! There won't be any difference, it's more an architecture question, because I would like to avoid the creation of Animals using the Animal constructor, so probably encapsulating it into a factory with an enum for each animal is the best solution?
@DarkVapor Indeed, that's another option. Perhaps something like an enum AnimalType and then a function like Animal* CreateAnimal(AnimalType type) which constructs them as necessary. That way you can keep the details of construction nicely separated from the rest of the code that uses the objects.
I do think this is the best indeed !
1

Usually, it's not a good practice to have members in the base class. Rather than that, create an interface and provide an implementation in the derived class returning the values:

class Animal {
protected:
    virtual std::string getName() const;
    virtual std::string getCategory() const;
};

class Bear : public Animal{
public:
    virtual std::string getName() const override {
        return std::string("Bear");
    }

    virtual std::string getCategory() const override {
        return std::string("Mamal");
    }
};

4 Comments

Are you sure about that? That seems very dirty to me ;-)
I don't think it's dirty at all, it's cleaner than having the base class polluted by members that don't have to be there. But if this is a good solution for you depends on what you're trying to achieve. What's exactly your use-case?
It seems dirty to me because that's the principle of constructors to initialize values in. I would keep virtual methods to redefine different behaviors in the class, rather than using it your way. Not to mention that if you have 100 classes, you will need to write a lot more code if you need to redefine those methods for each class.
Honestly, if the example you've given is not just an example but an actual use-case, don't use inheritance. There is no point to have a separate class for each animal. That is in case you're not planning to extend each animal class with some behaviour exclusive to every animal. Then you could just have one Animal class and pass the name and category to the constructor and just use this class. However, in case you are planning to extend each animal class with more functionality, put the members in the derived classes and create a pure interface (abstract class) that is common for all animals.
0

Inheritance is useful when you have different cases of implementation but still have the same working base behind. In your case if the only difference between all your animals is the name and category and that there's no specific implementations then I personally think this is not useful.

However what could be improved in your case is the need of 2 arguments that define the same thing (a Bear is always a mammal for example). Maybe a map could fix this issue in your case?

Comments

0

Making a class for each animal seems excessive. I did a school work before where I used an Animal class and I made the derived class into Predator and Prey. So, make the derived ones be specific types of animal, like Mammal, Fishes, etc. For your example, you can just use the single Animal class and call that Animal bear.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.