В чем разница между наследованием public
, private
и protected
в C++? Все вопросы, которые я нашел на SO, касаются конкретных случаев.
class A
{
public:
int x;
protected:
int y;
private:
int z;
};
class B : public A
{
// x is public
// y is protected
// z is not accessible from B
};
class C : protected A
{
// x is protected
// y is protected
// z is not accessible from C
};
class D : private A // 'private' is default for classes
{
// x is private
// y is private
// z is not accessible from D
};
Важное примечание: классы B, C и D содержат переменных x, y и Z. Это просто вопрос доступа.
Об использовании protected и Private наследование можно прочитать здесь.
Чтобы ответить на этот вопрос, я бы хотел сначала описать своими словами аксессоры member'ов. Если вы уже знаете это, переходите к заголовку "далее:".
Есть три аксессора, о которых я знаю: public
, protected
и private
.
Пусть:
class Base {
public:
int publicMember;
protected:
int protectedMember;
private:
int privateMember;
};
Base
, также знает, что Base
содержит publicMember
.Base
содержит protectedMember
.Base
, не знает о privateMember
.Под "известно" я подразумеваю "признавать существование и, следовательно, иметь доступ".
То же самое происходит с наследованием public, private и protected. Рассмотрим класс Base
и класс Child
, который наследуется от Base
.
public
, то все, что знает о Base
и Child
, также знает, что Child
наследует от Base
.protected
, только Child
и его дети знают, что они наследуют от Base
.private
, никто, кроме Child
, не знает о наследовании.Ограничения видимости наследование будет сделать код не в состоянии видеть, что некоторый класс наследует другой класс: неявное преобразование от производного к базовому выиграл't работа, и метод static_cast` от базового к производному выиграл'т работу.
Только члены и друзья класса могут увидеть частные наследования, и только члены/друзья и производные классы могут увидеть защищенного наследования.
общие наследования
кнопка класса : Public окно { };
охраняемых наследования
структура empty_pair_impl : защищена empty_class_1 { non_empty_class_2 второй; };
пара структуру : частная empty_pair_impl { non_empty_class_2 &ампер;второй() { вернуть это->второй; }
&ампер empty_class_1;первый() { вернуть this; // обратите внимание, мы возвращаемся это! } };
частный наследования
шаблон<StorageModel имя_типа> строки структуры : частная StorageModel { общественные: пустота realloc() { // использует унаследованные функции StorageModel::realloc(); } };
общие член
пара класса { общественные: Первый; Второй второй; };
окна класса { общественные: тип int getWidth() константный; };
охраняемых член
класса Stack { защищено: вектор<элемент> с; };
окна класса { защищено: пустота непредвиденное registerclass(window_descriptor Вт); };
частный член
окна класса { частная: инт ширина; };
Отметим, что c-стиля бросает намеренно позволяет литья производного класса к protected или Private базового класса в определенном и безопасном образе и тоже брошены в другом направлении. Этого следует избегать любой ценой, потому что он может сделать зависимый код на детали реализации, но, при необходимости, вы можете воспользоваться этой техникой.
Это связано с тем, как открытые члены базового класса открываются из производного класса.
Как отмечает litb, публичное наследование - это традиционное наследование, которое встречается в большинстве языков программирования. То есть оно моделирует отношения "IS-A". Приватное наследование, что AFAIK свойственно C++, является "ВЗАИМОДЕЙСТВИЕМ В ТЕРМИНАХ" отношений. То есть вы хотите использовать публичный интерфейс в производном классе, но не хотите, чтобы пользователь производного класса имел доступ к этому интерфейсу. Многие утверждают, что в этом случае вы должны агрегировать базовый класс, то есть вместо того, чтобы иметь базовый класс как приватную базу, сделать его членом производного класса, чтобы повторно использовать функциональность базового класса.
в Эти три ключевых слова используются в совершенно ином контексте, чтобы указать модель наследования видимости.
В этой таблице собраны все возможные комбинации компонент декларации и модель наследования, представив в результате чего доступ к компонентам для подкласса полностью определены.
Приведенной выше таблице, интерпретируется следующим образом (взгляните на первую строку):
если компонент заявил А общие и класс наследство а общие в результате доступ составляет общие.
Пример:
class Super {
public: int p;
private: int q;
protected: int r;
};
class Sub : private Super {};
class Subsub : public Sub {};
В результате доступ к переменным п
, п
, р
в класс суб составляет нет.
другой пример:
class Super {
private: int x;
protected: int y;
public: int z;
};
class Sub : protected Super {};
В результате доступ к переменным г
, Z
в класс суб составляет охраняемых и переменная " X " является нет.
более подробный пример:
class Super {
private:
int storage;
public:
void put(int val) { storage = val; }
int get(void) { return storage; }
};
int main(void) {
Super object;
object.put(100);
object.put(object.get());
cout << object.get() << endl;
return 0;
}
Теперь определим подкласс:
class Sub : Super { };
int main(void) {
Sub object;
object.put(100);
object.put(object.get());
cout << object.get() << endl;
return 0;
}
Определенных именованных суб-класс, который является подклассом класса под названием Супер
или суб
класс является производным от "супер" класса.
Суб
класса вводит ни новых переменных, ни новых функций. Означает ли это, что любой объект суб
класс наследует все черты, после "супер" класса, являясь, по сути, копия "супер" класс объектов?
Нет. Это не так.
Если мы скомпилировать следующий код, мы получим ничего, кроме ошибки компиляции, заявив, что методы " пут " и "получить" недоступны. Почему?
Когда мы опускаем спецификатор видимости, компилятор предполагает, что мы намерены применить так называемые наследования. Это означает, что все общие компоненты суперкласса превращаются в частный доступ, отдельный суперкласса компоненты выиграл'т быть доступны на всех. Это, следовательно, означает, что вам не разрешено использовать последний внутри подкласса.
Мы должны сообщить компилятору, что мы хотим сохранить ранее используемой политики доступа.
class Sub : public Super { };
не вводить в заблуждение: это не значит, что частная компоненты супер класс (для хранения переменной) превратятся в общественные, в несколько магическим образом. Частный компоненты останутся частный, общие останется общие.
Объектов суб
класс может делать то "почти" в одни и те же вещи, как и их старшие братья и сестры, созданные из "супер" класса. то"почти" по, поскольку факт нахождения подкласс также означает, что класс потерял доступ к закрытым компонентам класса. Мы не можем написать функцию-член суб
класс, который будет способен напрямую управлять переменной хранения.
Это очень серьезное ограничение. Есть ли обходной путь?
Да.
Третий уровень доступа называется охраняемых. Ключевое слово защищено означает, что компонент помечена ведет себя как публичное, когда используется любой из подклассов и выглядит как отдельный один для остального мира. -- Это справедливо только для публично унаследованных классов (например, класса в нашем примере) --
class Super {
protected:
int storage;
public:
void put(int val) { storage = val; }
int get(void) { return storage; }
};
class Sub : public Super {
public:
void print(void) {cout << "storage = " << storage;}
};
int main(void) {
Sub object;
object.put(100);
object.put(object.get() + 1);
object.print();
return 0;
}
Как вы видите в примере кода мы новую функциональность к классу суб
и он делает одну важную вещь: он обращается к переменной хранения от супер-класса.
Это не было бы возможным, если переменная была объявлена как private. В основной области видимости функции переменной остается скрытым, в любом случае, если вы пишете что-нибудь вроде:
object.storage = 0;
Компилятор сообщит вам, что это ошибка: 'инт супер::хранения' защищены
.
Наконец, последняя программа выдаст следующий результат:
storage = 101
Member in base class : Private Protected Public
Наследование тип : объект наследуется как:
Private : Inaccessible Private Private
Protected : Inaccessible Protected Protected
Public : Inaccessible Protected Public
1) Открытое Наследование:
а. Частные члены базового класса доступны в производном классе.
б. Защищенные члены базового класса остаются защищенными в производном классе.
С. Открытые члены базового класса остаются открытыми и в производном классе.
Так, другие классы могут использовать открытые члены базового класса через производный объект класса.
2) Защищенное Наследование:
а. Частные члены базового класса доступны в производном классе.
б. Защищенные члены базового класса остаются защищенными в производном классе.
С. Открытые члены базового класса становятся слишком защищенными членами производного класса.
Так, другие классы могут'т использовать открытые члены базового класса через производный объект класса, но они доступны для подкласса производных.
3) Частная Наследство:
а. Частные члены базового класса доступны в производном классе.
б. Защищены & открытые члены базового класса становятся закрытыми членами производного класса.
Таким образом, ни один из членов базового класса могут быть доступны другим классам через объект производного класса, так как они являются закрытыми в производном классе. Таким образом, даже подкласса производных класс может'т получить к ним доступ.
Модели общественного наследования это-отношения. С
class B {};
class D : public B {};
каждый Д
_ это ох Б
.
Индивидуальные модели наследования есть-реализовано-через отношения (или что там, что'называется). С
class B {};
class D : private B {};
А Д
- это не на B
, но все Д
использует Б
в ее реализации. Частная наследования, всегда могут быть устранены при использовании содержания:
class B {};
class D {
private:
B b_;
};
Это Д
, тоже можно реализовать с помощью "Б", в этом случае, используя его что
. Сдерживание является менее жесткой связи между типами наследования, так что в целом он следует отдавать предпочтение. Иногда с помощью сдерживания, а не приватное наследование не так удобно, как частное наследство. Часто, что'ы отмазка для лени.
Я не'т думаю, что кто-то знает, что "защищенных" моделей наследования. По крайней мере, я не'т видели никакого убедительного объяснения пока.
Если вы публично наследовать от другого класса, все знают, что вы унаследовали и может использоваться полиморфно кем-либо через базовый указатель класса.
Если вы наследуете protectedly сможете использовать вы полиморфно только вашим детям уроки.
Если вы наследуют в частном порядке, только сам сможешь исполнить методов родительского класса.
Что по сути символизирует знания остальных классов о ваших отношениях с вашими родителями класса
Защищенные данные-члены могут быть доступны любые классы, которые наследуют от класса. Члены личные данные, однако, не может. Позвольте'ы сказать, что мы имеем следующее:
class MyClass {
private:
int myPrivateMember; // lol
protected:
int myProtectedMember;
};
Из вашего дополнения к данному классу, ссылаясь на это.myPrivateMember выиграл't работа. Тем не менее, это.myProtectedMember будет. Значение по-прежнему герметичны, поэтому если у нас есть экземпляр этого класса под названием myObj
, затем `myObj.myProtectedMember выиграл'т работу, так он похож на закрытый элемент данных.
Accessors | Base Class | Derived Class | World
—————————————+————————————+———————————————+———————
public | y | y | y
—————————————+————————————+———————————————+———————
protected | y | y | n
—————————————+————————————+———————————————+———————
private | | |
or | y | n | n
no accessor | | |
y: accessible
n: not accessible
Основываясь на этот пример для Java... я думаю, что столик стоит тысячи слов :)
Резюме:
При наследовании, вы можете (в некоторых языках) изменить тип защиты элемента данных в определенном направлении, например, из protected в public.
Частные члены базового класса могут быть доступны только члены базового класса .
Открытые члены базового класса можно обращаться к членам базового класса, членами производного класса, а также члены, которые не входят в базовый класс и производный класс.
Защищенные члены базового класса могут быть доступны членам базового класса, а также членов его производного класса.
частный: основание
охраняемых: основание + производные
общие: база + производные + любой другой член
Я нашла простой ответ и так думал о публикации для меня слишком в будущем.
Его от http://www.learncpp.com/cpp-tutorial/115-inheritance-and-access-specifiers ссылки/
class Base
{
public:
int m_nPublic; // can be accessed by anybody
private:
int m_nPrivate; // can only be accessed by Base member functions (but not derived classes)
protected:
int m_nProtected; // can be accessed by Base member functions, or derived classes.
};
class Derived: public Base
{
public:
Derived()
{
// Derived's access to Base members is not influenced by the type of inheritance used,
// so the following is always true:
m_nPublic = 1; // allowed: can access public base members from derived class
m_nPrivate = 2; // not allowed: can not access private base members from derived class
m_nProtected = 3; // allowed: can access protected base members from derived class
}
};
int main()
{
Base cBase;
cBase.m_nPublic = 1; // allowed: can access public members from outside class
cBase.m_nPrivate = 2; // not allowed: can not access private members from outside class
cBase.m_nProtected = 3; // not allowed: can not access protected members from outside class
}
По сути, это защита доступа к публичным и защищенным членам базового класса в производном классе. При публичном наследовании производный класс может видеть публичные и защищенные члены базового. При частном наследовании - нет. При наследовании protected производный класс и все классы, производные от него, могут их видеть.