c++classinheritance

Base class method working on private member of derived class


I am trying to let PrintVal() of the base class print the value of private member m_val of the derived class, but it appears it is still printing 1 instead of 2.
Since d is a instance of derived class, why didn't it print 2 instead?

#include <iostream>

class base
{
public:
    void PrintVal()
    {
        std::cout << m_val <<std::endl;
    }

private:

    int m_val = 1;
};

class derived : public base
{
public:
//    void PrintVal()
//    {
//        std::cout << m_val <<std::endl;
//    }

private:
    int m_val = 2;
};

int main()
{
    derived d;
    d.PrintVal();

    return 0;
}

How to use PrintVal() in the base class to print m_val in the derived class? Thank you so much.


Solution

  • In your current code there are 2 separate variables: base::m_val and derived::m_val.
    PrintVal() is a method of base and therefore accesses base::m_val.

    You can use a virtual method to get the value.

    This virtual method in base will return base::m_val, and the override in derived will return derived::m_val.

    PrintVal in base can call this virtual method to print the relevant value.

    This is shown below:

    #include <iostream>
    
    class base {
    public:
        void PrintVal() {
            // Use the virtual method to get the value:
            std::cout << GetVal() << std::endl;
        }
    
    private:
        virtual int GetVal() { return m_val; } // will return `base::m_val`
        int m_val = 1;
    };
    
    class derived : public base {
    public:
    
    private:
        int GetVal() override { return m_val; } // will return `derived::m_val`
        int m_val = 2;
    };
    
    int main() {
        derived d;
        d.PrintVal();
    }
    

    Output:

    2
    

    Live demo 1


    If you have access to C++23, there's an elegant solution using a this auto& self parameter (suggested by @WeijunZhou in a comment) but it will work only if you can make m_val public in derived:

    #include <iostream>
    
    class base {
    public:
        void PrintVal(this auto& self) {
            std::cout << self.m_val <<std::endl;
        }
    
    private:
        int m_val = 1;
    };
    
    class derived : public base {
    public:
        int m_val = 2;
    };
    
    int main() {
        derived d;
        d.PrintVal();
    }
    

    Live demo 2