Search code examples
c++inheritancepolymorphismprivateprotected

C++ - Accessing protected/private members of a base class


I'm trying out a small example to practice the concepts of inheritance, and polymorphism. Here is a simplified version of my code:

class Shape {
protected:
    int length;
    int width;
public:
    virtual void setLength(int l) = 0;
    virtual void setWidth(int w) = 0;
};

class Rectangle : public Shape {
public:
    Rectangle(int l, int w)
    : length(l), width(w)
    { }

    void setWidth(int w) { width = w; }
    void setLength(int l) { length = l; }
};

int main() {
    Rectangle r(0,0);
}

I'm trying to run the above program. However, when I compile rectangle.cc, I get the following error

g++ -c rectangle.cc

rectangle.cc: In constructor 'Rectangle::Rectangle(int, int)':
rectangle.cc:13:5: error: class 'Rectangle' does not have any field named 'length'
rectangle.cc:13:16: error: class 'Rectangle' does not have any field named 'width'

To my understanding, in public inheritance, protected members of the base class become protected members of the derived class and should be able to e accessed like public members. Is that incorrect? Also, how would the code then need to be modified if length and width were private members of the base class?


Solution

  • To my understanding, in public inheritance, protected members of the base class become protected members of the derived class and should be able to e accessed like public members. Is that incorrect?

    This is mostly true. Public and protected members of base classes are accessible in derived classes (public inheritance doesn't matter here - that only affects outside observers' access). However, class members (of any access) can only be initialized in their own class. In this case, only Shape can initialize length and width - it doesn't matter that they're protected, the same would be true if they were public or private.

    You would have to add a constructor to do this, which your Rectangle constructor could simply delegate to. This works regardless of the access control of length and width (as long as the Shape constructor is public or protected):

    struct Shape {
        Shape(int l, int w) : length(l), width(w) { }
    };
    
    struct Rectangle {
        Rectangle(int l, int w) : Shape(l, w) { }
    };
    

    Or, for completeness, you could just assign them, but definitely prefer to have Shape initialize them. Additionally, this only works if the members in question are public or protected:

    Rectangle(int l, int w) {
        length = l;
        width = w;
    }
    

    Note that your setWidth() and setLength() functions are fine - you do have access to those protected members in Rectangle's member functions. Just not for initialization.