call non-virtual method of derived class in polymorphic hierarchy of library that can't be modified without down-casting

77 Views Asked by At

Today interviewer told me that Visitor pattern & double dispatch can be used to call non-virtual method of derived class from 3rd party library which source code can't be accessed/changed (this is what they do in their production code, he said). For example, in below code they pass reference to Animal into Bar and call specific methods of classes derived from Animal without using dynamic_cast. Point is that dynamic_cast isn't used anywhere in their implementation. Templates aren't used.

I did rephrased my question to interviewer few times so there's no misunderstanding.

I don't see a way implementing Visitor without adding Accept method to classes in library that will utilize argument overloading on Visitor::Visit by passing *this to it.

Is this possible? Or interviewer confused it with other language that probably allow something C++ doesn't? Because he was emphasizing that Visitor and double dispatch is used together, whereas AFAIK in C++ double dispatch is Visitor, meaning Visitor is used to implement double dispatch. I hope I didn't lost you. Thanks for your time!

import <iostream>;


namespace LibraryCode // can't be changed
{
    class Animal
    {
    public:
        virtual ~Animal() = default;

    public:
        virtual void move() const { std::cout << "Animal: moving!" << std::endl; };

        void breath() const { std::cout << "Animal: breathing!" << std::endl; }
    };

    class Duck : public Animal
    {
    public:
        void move() const override { std::cout << "Duck: flying!" << std::endl; }

        void make_nest() const { std::cout << "Duck: making nest!" << std::endl; }
    };

    class Dolphin : public Animal
    {
    public:
        void move() const override { std::cout << "Dolphin: swimming!" << std::endl; }

        void make_air_bubble() const { std::cout << "Dolphin: making air bubble!" << std::endl; }
    };
}

void Bar(LibraryCode::Animal const& a)
{
    a.breath();
    a.move();

    // w/o using dynamic_cast call make_nest if it's a Duck

    // w/o using dynamic_cast call make_air_bubble if it's a Dolphin
}

int main()
{
    Bar(LibraryCode::Duck{});
    Bar(LibraryCode::Dolphin{});
}
0

There are 0 best solutions below