Search code examples
c++inheritancediamond-problem

Why do I have to explicitly define a method provided by an inhereted class?


Consider the following:

#include <string>

struct animal
{
public:
    virtual std::string speak() = 0;
};

struct bird : public animal
{
public:
    std::string speak()
    {
        return "SQUAK!";
    }
};

struct landAnimal : public animal
{
    virtual int feet() = 0;
};


struct sparrow : public bird, public landAnimal
{
    int feet() { return 2; }
    // This solves it, but why is it necessary, doesn't bird provide this?
    // std::string speak(){ return this->speak(); } 
};

int main()
{
    sparrow tweety = sparrow();
}

Compiling it, you'll get:

1>ex.cpp(35): error C2259: 'sparrow': cannot instantiate abstract class
1>  ex.cpp(35): note: due to following members:
1>  ex.cpp(35): note: 'std::string animal::speak(void)': is abstract
1>  ex.cpp(10): note: see declaration of 'animal::speak'

Why do you need the commented method to get it to compile?


Solution

  • Because, unlike what you tagged, you don't have diamond inheritance. Your sparrow is two animals, and only one of them is made concrete by bird. The other one, inherited through landAnimal, is not.

    What you need to obtain an actual diamond is virtual inheritance, but as you'll find out it comes with an extensive list of caveats.

    On a side note, as Martin Bonner rightfully points out:

    It's probably worth pointing out that the "fix" isn't a fix at all. Any call to sparrow::speak() will cause infinite recursion. It would need to be std::string speak() { return Bird::speak(); }.