2016-03-27 4 views
2

Я пробую небольшой пример для практики концепций наследования и полиморфизма. Вот упрощенная версия моего кода: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' 

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

+0

это поможет, если вы снизили этом [mcve], так ошибка легче увидеть. Большая часть кода, который вы опубликовали, не имеет значения. – juanchopanza

+0

@Q_A Чтобы дать вам представление о том, что мы подразумеваем под минимальным, я уменьшил ваш код до двух десятков строк, которые воспроизводят ту же ошибку. Надеюсь, ты не против. Обратите внимание, что многие из функций не имеют отношения к проблеме, с которой вы столкнулись, и вам не нужно создавать массив 'Shape's, чтобы воспроизвести его и т. Д. – Barry

+0

Спасибо, я буду помнить это –

ответ

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 функций УЧАСТНИКА. Просто не для инициализации.

+0

Спасибо. Как бы изменился код, если длина и ширина были частными членами базового класса? –

+0

@Q_A Наличие 'Shape' инициализации собственных членов означает, что управление доступом не имеет значения. В этом случае, хотя 'setWidth()' и 'setLength()' быть виртуальными, не имеет особого смысла, производные классы фактически не могли бы установить ничего. – Barry

2

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

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

+0

Собственно, компилятор ошибка очень связана. –

+0

Чтобы уточнить: ошибка компилятора не связана с «защищенными членами базового класса, которые не становятся защищенными членами производного класса» – juanchopanza

+0

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

1

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

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

при использовании защищенных ... общественность и защищена от базового класса становится защищены