Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 479
Q_A Avatar asked Feb 07 '23 09:02

Q_A


2 Answers

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.

like image 170
Barry Avatar answered Feb 16 '23 03:02

Barry


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.

like image 41
Sam Varshavchik Avatar answered Feb 16 '23 02:02

Sam Varshavchik