Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Calling derived method from base class pointer vector



  • I have a base class and a bunch of derived classes from it, with a particular virtual function that is overriden in the derived classes, let's say:

    class Base : public QMainWindow 
    {
        protected:
        virtual void handleSomething() = 0; 
        ...
    }
    class Derived1 : public Base
    {
        public:
        void handleSomething() override; 
        ...
    }
    class Derived2 : public Base
    {
        public:
        void handleSomething() override; 
        ...
    }
    class Derived3 : public Base
    {
        public:
        void handleSomething() override; 
        ...
    }
    

    To work with the derived classes, I created a pointer that collects them all, but in that case I had to declare it with the base class like this:

    QVector<Base*> vector;
    

    Now I am trying to call the overriden methods in a loop like this:

    foreach(auto widget, vector)
    {
        widget->handleSomething();
    }
    

    But I get the following error:

    'handleSomething' is a protected member of 'Base'
    

    which means that the loop is trying to call the base method instead of the derived ones. How could I do to call the overriden methods?



  • @diego-qt
    I am not as knowledgeable about C++ as some experts here, so I stand to be corrected. However, so far as I can see the behaviour is correct. If the base virtual method is protected then you can only call that from within/derived/friend of the base class. The fact that you choose to declare overrides of the base protected as public is neither here nor there. You could call them (the publics) from the outside world, but not via the base.

    If you are looking for a workaround you could dynamic_cast<> (or qobject_cast<>) your widget to find the correct derived class and then call that way, because then the method is public. But of course that is not as neat as via the base class, and requires the caller to know about all the derived classes.


  • Lifetime Qt Champion

    @diego-qt Why is the method protected in base class but public in derived classes? This is going to confuse other developers.



  • @jsulm I thought it was the correct way of overriding virtual methods, setting them as protected so the derived classes can override them. But I think I was wrong. I changed the base method into public and the error disappeared. Thanks for the observation @JonB



  • @diego-qt said in Calling derived method from base class pointer vector:

    setting them as protected so the derived classes can override them

    All virtual methods can be overridden (even private), the issue is where you can call them from. private => base class only, protected => derived classes too, public => outside world too. You want to call widget->handleSomething();, so you need public.

    I didn't suggest changing the base to public as I assumed the point was that your Base class virtual method had been written protected by someone else and had to stay like that!



  • @diego-qt

    You could try widget->Derived1::handleSomething(); to call the function from your derived class, even tho it would break your variability, because you have to decide what derived class you want to call in your foreach loop.
    (Don't even know if it would work in your case)

    I would make it public (like you already did) in Base to avoid the issues @JonB and @jsulm stated above.



  • To continue the same way as @JonB
    I think the reason is that C++ is not a dynamic language as objectiveC or Java,

    foreach(Base* widget, vector)    / I hate auto !!!
    {
        widget->handleSomething();
    }
    

    Here C++ see widget is a Base instance and when the compiler looks at the handle method, it sees it as protected and stop at it with an error.
    C++ is not so smart :)


Log in to reply