Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can't access public base member from derived pointer

Why does this code not compile? (gcc 4.7.0)

// Class with a simple getter/setter pair.
class Base {
public:
    Base () : m_Value(0) {  }

    virtual ~Base () {  }

    // Getter
    virtual int value () { return m_Value; }

    // Setter
    virtual void value (int Val) { m_Value = Val; }

private:
    int m_Value;
};

// Derived class overrides the setter.
class Derived : public Base {
public:
    void value (int Val) {
            // do some stuff here...
    }
};

int main()
{
    Derived * instance = new Derived();
    int x = instance->value();  // ERROR
    return 0;
}

Build log:

test.cpp: In function 'int main()':
test.cpp:29:25: error: no matching function for call to 'Derived::value()'
test.cpp:29:25: note: candidate is:
test.cpp:21:7: note: virtual void Derived::value(int)
test.cpp:21:7: note:   candidate expects 1 argument, 0 provided

Why does the compiler fail to see 'int value()' from Base when using Derived*?

Changing

Derived * instance = new Derived();

to

Base * instance = new Derived();

works (but I need the derived pointer in my case).

Also renaming the base getter/setter functions to say getValue() and setValue(int) works. I can use various workarounds for my code, but I was just curious as to why this code fails to compile.

like image 658
Daniel Hanrahan Avatar asked Dec 05 '22 16:12

Daniel Hanrahan


2 Answers

This is how the language works: When a child class overrides a member of a name it hides all the non-overridden names in the parent. This is to prevent accidentally combining base and parent methods that should be overridden as sets.

You can put using Base::value; in your child class to bring in the parent methods.

like image 123
Mark B Avatar answered Dec 09 '22 15:12

Mark B


The function value in the derived class hides the function in the base class.

You need to bring the base class functions into the scope of the derived class as:

class Derived : public Base {
public:

    using Base::value;   //<---- note this

    void value (int Val) {
            // do some stuff here...
    }
};
like image 30
Nawaz Avatar answered Dec 09 '22 14:12

Nawaz