3
votes

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?

3
It would help if you reduced this to an minimal reproducible example so the error is easier to see. Most of the code you posted is irrelevant.juanchopanza
@Q_A To give you a sense of what we mean by minimal, I reduced your code down to just two dozen lines that reproduce the same error. I hope you don't mind. Note that many of the functions are irrelevant to the problem you're having, nor do you need to create an array of Shapes to reproduce it, etc.Barry
Thanks, I'll keep that in mindQ_A

3 Answers

4
votes

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.

2
votes

No, protected members of the base class do not become protected members of the derived class. Protected members of the base class are accessible by the derived class, unlike private members, and they remain protected, in the derived class's namespace (so the same thing applies to the derived class of the derived class, and so on).

But protected members of the base class are still members of the base class, and the base class's constructor is still responsible for constructing them, not the derived class's constructor.

1
votes

remove the part : length(l), width(w) if u want to use length and width(inherited) in the derived class u can use it just by taking its name e.g. length.. done... if u happen to have the same named field 'length' in the derived class then to use the derived class's 'length' use this->length...

when inheriting... public access specifier states that public from base class become public in the derived class protected from base class become protected...

when using protected... public and protected from base class become protected