Search code examples
c++polymorphismvirtual

Is overriding a function with derived class argument considered name hiding?


I is this considered name hiding?
As according to the output it is:

class A
{
public:
    A(){}
    virtual bool f(A& a) {
        std::cout << "A" << std::endl;
        return true;
    }
};

class B : public A
{
    std::string s;
public:
    B(){}
    bool f(B& a) {
        std::cout << "B" << std::endl;
        return s == a.s;
    }
};

int main()
{
    A* a = new B;
    B b;
    a->f(b);
}

This prints A, and if I want to achieve the polymorphic behaviour, I need to make the derived class's f's argument the same as the base classes. But in that case I don't have access to s in the derived class function. Is this a design deadlock or I am messing up the OOD principles?


Solution

  • It seems you want multiple dispatch.

    Double dispatch pattern is a solution.

    With c++17, we have std::variant which might do the dispatching for us:

    class A;
    class B;
    
    using VariantA = std::variant<A*, B*, C*>;
    using VariantConstA = std::variant<const A*, const B*, const C*>;
    
    class A
    {
    public:
        virtual ~A() = default;
        virtual VariantA AsVariant() { return this; }
        virtual VariantConstA AsVariant() const { return this; }
    
        friend bool operator==(const A&, const A&);
    };
    
    class B : public A
    {
        std::string s;
    public:
        B(std::string s) : s(s) {}
        VariantA AsVariant() override { return this; }
        VariantConstA AsVariant() const override { return this; }
    
        friend bool operator==(const B& lhs, const B& rhs);
    };
    
    // class C
    
    struct EqualVisitor
    {
        template <typename T>
        bool operator() (const T& lhs, const T& rhs) const { return lhs == rhs; }
    
        template <typename T1, typename T2>
        bool operator() (const T1&, const T2&) const { return false; }
    };
    
    
    bool AreEqual(const A& lhs, const A& rhs)
    {
        return std::visit(EqualVisitor{}, lhs.AsVariant(), rhs.AsVariant());
    }
    

    Demo