C++ - доступ к защищенным / закрытым членам базового класса


Я пробую небольшой пример, чтобы практиковать концепции наследования и полиморфизма. Вот упрощенная версия моего кода:

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);
}

Я пытаюсь запустить вышеупомянутую программу. Однако, когда я компилирую rectangle.cc, я получаю следующую ошибку

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'

Насколько я понимаю, при публичном наследовании защищенные члены базового класса становятся защищенными членами производного класса и должны быть доступны как открытые члены. Разве это неверно? Кроме того, как бы код тогда нужно изменить, если длина и ширина были частными членами базового класса?

3 2

3 ответа:

Насколько я понимаю, при публичном наследовании защищенные члены базового класса становятся защищенными членами производного класса и должны быть доступны как открытые члены. Разве это неверно?

Это В основном верно. Открытые и защищенные члены базовых классов доступны в производных классах (public наследование здесь не имеет значения - это влияет только на доступ внешних наблюдателей). Однако члены класса (любого доступа) могут быть только инициализированы в своем собственном классе. В этом случае только Shape может инициализировать length и width - неважно, что они protected, то же самое было бы верно, если бы они были public или private.

Для этого вам придется добавить конструктор, которому ваш конструктор Rectangle может просто делегировать права. Это работает независимо от управления доступом length и width (пока конструктор Shape является public или protected):
struct Shape {
    Shape(int l, int w) : length(l), width(w) { }
};

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

Или, для полноты картины, вы можете просто назначить их, но определенно предпочитаю иметь Shape инициализировать их. Кроме того, это работает только в том случае, если рассматриваемые члены public или protected:

Rectangle(int l, int w) {
    length = l;
    width = w;
}
Обратите внимание, что ваши функции setWidth() и setLength() хороши - у вас есть доступ к этим защищенным членам в функциях-членахRectangle. Только не для инициализации.

Нет, защищенные члены базового класса не становятся защищенными членами производного класса. Защищенные члены базового класса доступны производному классу, В отличие от закрытых членов, и они остаются защищенными в пространстве имен производного класса (поэтому то же самое относится к производному классу производного класса и т. д.).

Но защищенные члены базового класса по-прежнему являются членами базового класса, и конструктор базового класса по-прежнему отвечает за построение они, а не конструктор производного класса.

Удалить деталь: длина (l), ширина (w) если вы хотите использовать длину и ширину (наследуемые) в производном классе, вы можете использовать его, просто взяв его имя, например length.. сделано... если у вас есть то же самое именованное поле 'length' в производном классе, то для использования производного класса 'length' используйте это->length...

При наследовании... публичного доступа спецификатор утверждает, что общественность от базового класса становятся публичными в производном классе защищен от базового класса становятся защищенными...

При использовании защищенный... публичный и защищенный от базового класса становятся защищенными