Protected c что это
Перейти к содержимому

Protected c что это

  • автор:

Protected c что это

Все поля, методы и остальные компоненты класса имеют модификаторы доступа . Модификаторы доступа позволяют задать допустимую область видимости для компонентов класса. То есть модификаторы доступа определяют контекст, в котором можно употреблять данную переменную или метод.

В языке C# применяются следующие модификаторы доступа:

Модификаторы доступа public, protected, internal, private в языке программирования C# и в .NET

  • private : закрытый или приватный компонент класса или структуры. Приватный компонент доступен только в рамках своего класса или структуры.
  • private protected : компонент класса доступен из любого места в своем классе или в производных классах, которые определены в той же сборке.
  • file : добавлен в версии C# 11 и применяется к типам, например, классам и структурам. Класс или структура с такми модификатором доступны только из текущего файла кода.
  • protected : такой компонент класса доступен из любого места в своем классе или в производных классах. При этом производные классы могут располагаться в других сборках.
  • internal : компоненты класса или структуры доступен из любого места кода в той же сборке, однако он недоступен для других программ и сборок.
  • protected internal : совмещает функционал двух модификаторов protected и internal . Такой компонент класса доступен из любого места в текущей сборке и из производных классов, которые могут располагаться в других сборках.
  • public : публичный, общедоступный компонент класса или структуры. Такой компонент доступен из любого места в коде, а также из других программ и сборок.

Стоит отметить, что эти модификаторы могут применяться как к компонентам класса, так и к компонентам структуры за тем исключением, что структуры не могут использовать модификаторы private protected , protected и protected internal , поскольку структуры не могут быть унаследованы.

Все классы и структуры, определенные напрямую вне других типов (классов и структур) могут иметь только модификаторы public , file или internal .

Мы можем явно задать модификатор доступа, а можем его и не указывать:

public class Person < string name; public Person(string name) < this.name = name; >public void Print() => Console.WriteLine($"Name: "); >

Если для компонентов не определен модификатор доступа, то по умолчанию для них применяется модификатор private . Например, в примере выше переменная name неявно будет иметь модификатор private .

Классы и структуры, которые объявлены без модификатора и которые расположены вне других типов, по умолчанию имеют доступ internal , а вложенные классы и структуры, как и остальные компоненты классов/структур имеют модификатор private . Например:

class Phone < struct Camera < >>

Здесь класс Phone не является вложенным ни в один другой класс/структуру, поэтому неявно имеет модификатор internal . А структура Camera является вложенной, поэтому, как и другие компоненты класса, неявно имеет модификатор private

Модификаторы в рамках текущего проекта

Посмотрим на примере и создадим следующий класс State:

class State < // все равно, что private string defaultVar; string defaultVar ="default"; // поле доступно только из текущего класса private string privateVar = "private"; // доступно из текущего класса и производных классов, которые определены в этом же проекте protected private string protectedPrivateVar = "protected private"; // доступно из текущего класса и производных классов protected string protectedVar = "protected"; // доступно в любом месте текущего проекта internal string internalVar = "internal"; // доступно в любом месте текущего проекта и из классов-наследников в других проектах protected internal string protectedInternalVar = "protected internal"; // доступно в любом месте программы, а также для других программ и сборок public string publicVar = "public"; // по умолчанию имеет модификатор private void Print() =>Console.WriteLine(defaultVar); // метод доступен только из текущего класса private void PrintPrivate() => Console.WriteLine(privateVar); // доступен из текущего класса и производных классов, которые определены в этом же проекте protected private void PrintProtectedPrivate() => Console.WriteLine(protectedPrivateVar); // доступен из текущего класса и производных классов protected void PrintProtected() => Console.WriteLine(protectedVar); // доступен в любом месте текущего проекта internal void PrintInternal() => Console.WriteLine(internalVar); // доступен в любом месте текущего проекта и из классов-наследников в других проектах protected internal void PrintProtectedInternal() => Console.WriteLine(protectedInternalVar); // доступен в любом месте программы, а также для других программ и сборок public void PrintPublic() => Console.WriteLine(publicVar); >

Так как класс State не имеет явного модификатора, по умолчанию он имеет модификатор internal , поэтому он будет доступен из любого места данного проекта, однако не будет доступен из других программ и сборок.

Класс State имеет шесть полей для каждого уровня доступа. Плюс одна переменная без модификатора, которая является закрытой (private) по умолчанию. А также определено семь методов с разными модификаторами, которые выводят значения соответствующих переменных на консоль. Поскольку все модификаторы позволяют использовать компоненты класса внутри данного класса, то и все переменные класса, в том числе закрытые, у нас доступны всем его методам, так как все находятся в контексте класса State.

Теперь посмотрим, как мы сможем использовать переменные класса State в другом классе, который, допустим, будет называться StateConsumer и который расположен в том же проекте :

class StateConsumer < public void PrintState() < State state = new State(); // обратиться к переменной defaultVar у нас не получится, // так как она имеет модификатор private и класс StateConsumer ее не видит Console.WriteLine(state.defaultVar); //Ошибка, получить доступ нельзя // то же самое относится и к переменной privateVar Console.WriteLine(state.privateVar); // Ошибка, получить доступ нельзя // обратиться к переменной protectedPrivateVar не получится, // так как класс StateConsumer не является классом-наследником класса State Console.WriteLine(state.protectedPrivateVar); // Ошибка, получить доступ нельзя // обратиться к переменной protectedVar тоже не получится, // так как класс StateConsumer не является классом-наследником класса State Console.WriteLine(state.protectedVar); // Ошибка, получить доступ нельзя // переменная internalVar с модификатором internal доступна из любого места текущего проекта // поэтому можно получить или изменить ее значение Console.WriteLine(state.internalVar); // переменная protectedInternalVar так же доступна из любого места текущего проекта Console.WriteLine(state.protectedInternalVar); // переменная publicVar общедоступна Console.WriteLine(state.publicVar); >>

Таким образом, в классе StateConsumer мы смогли только обратиться к переменным internalVar, protectedInternalVar и publicVar, так как их модификаторы позволяют использовать в данном контексте.

Аналогично дело обстоит и с методами:

class StateConsumer < public void PrintState() < State state = new State(); state.Print(); //Ошибка, получить доступ нельзя state.PrintPrivate(); // Ошибка, получить доступ нельзя state.PrintProtectedPrivate(); // Ошибка, получить доступ нельзя state.PrintProtected(); // Ошибка, получить доступ нельзя state.PrintInternal(); // норм state.PrintProtectedInternal(); // норм state.PrintPublic(); // норм >>

Здесь нам оказались доступны только три метода: PrintInternal, PrintProtectedInternal, PrintPublic, которые имееют соответственно модификаторы internal, protected internal, public.

Модификаторы в рамках сборок

Допустим, у нас есть проект (и соответственно сборка) MyLib, в которой определены три класса:

namespace MyLib; // класс доступен из других сборок public class PublicState < internal void PrintInternal() =>Console.WriteLine(«internal»); protected internal void PrintProtectedInternal() => Console.WriteLine(«protected internal»); public void PrintPublic() => Console.WriteLine(«public»); > // класс доступен только в текущей сборке — по умолчанию internal class DefaultState < >// класс доступен только в текущей сборке internal class InternalState

Здесь классы DefaultState и InternalState имеют модификатор internal , поэтому доступны только в текущем проекте.

Класс PublicState модификатором public доступен из других проектов. Однако его метод PrintInternal() доступен только в текущем проекте. Вне текущего проекта доступен только его метод PrintPublic и PrintProtectedInternal() (доступен в другом проекте только в классах-наследниках).

Допустим, мы подключаем сборку этого проекта MyLib в другой проект, где есть класс StateConsumer:

using MyLib; class StateConsumer < public void PrintState() < // Ошибка DefaultState - по умолчанию internal, поэтому нет доступа DefaultState defaultState = new DefaultState(); // Ошибка InternalState - internal, поэтому нет доступа InternalState internalState = new InternalState(); // норм, PublicState - public, доступен из других программ PublicState publicState = new PublicState(); // Ошибка, нет доступа - метод доступен только в свой сборке publicState.PrintInternal(); // Ошибка, нет доступа - StateConsumer НЕ является классом-наследником от класса PublicState, // поэтому метод не доступен publicState.PrintProtectedInternal(); // нет доступа // норм - общедоступный метод publicState.PrintPublic(); // норм >>

Модификаторы доступа в языке программирования C# и в .NET

В классе StateConsumer есть доступ только к классу PublicState и его методу PrintPublic , потому что они имеют модификатор public . К остальной функциональности подключенной сборки StateConsumer доступа не имеет.

Благодаря такой системе модификаторов доступа можно скрывать некоторые моменты реализации класса от других частей программы.

Файл как область видимости

C# 11 был добавлен еще один модификатор видимости — file , который применяется к классам, структурам, делегатам, перечислениям, интерфейсам. Типы с этим модификатором могут использоваться только внутри текущего файла кода.

file class Person

Данный модификатор не может использоваться в паре с другими модификаторами.

C++ для всех

Тема довольно избита, однако, я всё-таки решил начать с неё. Думаю, новичкам будет полезно.

Итак, public, private и protected — это модификаторы доступа, а не видимости, как ошибочно думают некоторые. Private члены видны снаружи класса, но не доступны.

Теперь кратко, кому какой доступ они предоставляют.

  • Public — доступ открыт всем, кто видит определение данного класса.
  • Private — доступ открыт самому классу (т.е. функциям-членам данного класса) и друзьям (friend) данного класса, как функциям, так и классам.
  • Protected — доступ открыт классам, производным от данного.

Далее приведены примеры доступа с указанием какие поля в каких местах программы доступны.

class some < friend void f(some&); public: int a_; protected: int b_; private: int c_; >; void f(some& obj) < obj.a_ = 0; // OK obj.b_ = 0; // OK obj.c_ = 0; // OK >void g(some& obj) < obj.a_ = 0; // OK obj.b_ = 0; // compile time error obj.c_ = 0; // compile time error >class derived : public some < derived() < a_ = 0; // OK b_ = 0; // OK c_ = 0; // compile time error >>;

В C++ существует public-наследование, private-наследование и protected-наследование. В зависимости от того, какой тип используется, изменяется доступ к членам базового класса для клиентов производного. В таблице сведена информация об этом изменении.

Исходный модификатор доступа
public private protected
public-наследование public private protected
private-наследование private private private
protected-наследование protected private protected

Следует добавить, что производный класс может изменить модификатор доступа с protected на public, разместив using объявление в соответствующей секции класса:

class some < public: int a; protected: int b; private: int c; >; class derived : public some < public: using some::b; >; void f(derived& obj) < obj.b = 0; // OK >

Напоследок приведу несколько приёмов, с помощью которых можно «достучаться» до закрытых функций или данных. Допустим, у нас есть класс some и нам нужно обнулить закрытую переменную c:

    Модифицировать определение класса, добавив друга (функцию или класс)

class some < friend class some_friend; public: int a; protected: int b; private: int c; >; class some_friend < public: static void hack(some& obj) < obj.c = 0; >>;

#define private public class some < public: int a; protected: int b; private: int c; >; void hack(some& obj)

class some < public: int a; protected: int b; private: int c; >; class hack_some < public: int a; int b; int c; >; void h(some& obj) < reinterpret_cast(&obj)->c = 0; >
class some < public: int a; template void func(void) < a = b + c; >protected: int b; private: int c; >; class hack_template_param<>; template void some::func(void) < c = 0; >void hack(void) < some o; o.func(); >;

Очевидно, что способ с reinterpret_cast работает только для доступа к закрытым членам данных или вызова виртуальных функций. Остальные же способы позволяют как модифицировать закрытые данные, так и вызывать закрытые невиртуальные методы.

UPD (31.08.2013): Для компиляторов GCC и CLANG существует опция -fno-access-control, которая позволяет отключить контроль доступа к членам класса со стороны компилятора.

UPD (31.08.2013): Переформатировал исходный код под использование встроенного плагина вордпресса.

Protected c что это

Написание статьи о protected привело к написанию этой. Я понял для какого из случаев предназначены модификаторы доступа private , public и protected .

  • private — Модификатор доступа, обозначющий, что программист будет использовать элементы класса только внутри непосредственно основного своего класса.
  • public — Модификатор доступа, обозначающий, что программист будет использовать элементы класса либо в других частях программы, либо в других классах.
  • protected — Модификатор доступа, обозначающий, что программист будет использовать элементы класса либо внутри непосредственно своего основного класса, либо непосредственно в своём потомке-классе.

Сейчас я попробую описать то же самое используя художественный стиль (может кому-то пригодиться).

Класс-наследник имеет поля и функции-члены базового класса, но не имеет права обращаться к собственным ( private ) полям и функциям базового класса. Вот и выходит так, что у основного класса есть такая часть, которую от сердца ему не оторвать: все наследники о ней знают, но использовать её не могут, так как родитель отказался передавать ту часть по наследству. Такая часть — это private .

Да вот мучает совесть родителя, не может родитель оставить детей без наследства, решает передать некоторую часть того, что у него есть, всем своим потомкам. Передаётся эта тайна от родителя к потомку, но скрыта она от всех посторонних и доступна исключительно детям собственным класса. Такая часть — это protected .

А чтобы не вспоминали родителя словом плохим, родитель передаёт еще часть наследства своим потомкам, и эта часть наследства озвучивается публично. Коли о наследстве озвучивается публично, то та часть, о которой озвучивается, может попасть не в руки потомков и использовать её сможет любой шарлатан. Такая часть — public .

Так вот обстоят дела с наследованием.

Иногда задают вопрос: » Если мы наследуем класс, наследуются ли приватные поля (члены)? . Ответ — да. Это легко проверить.

//Приватные поля наследуются clang Листинг #1
using namespace std ;
int a , b , c ; //По умолчанию private.
class B : public A //Применили наследование и на основе класса A создали класс B
class C //Независимый класс
cout < < sizeof ( A ) < < endl ; //Вывели на экран размер объекта от класса A cout < < sizeof ( B ) < < endl ; //Вывели на экран размер объекта от класса B cout < < sizeof ( C ) < < endl ; //Вывели на экран размер объекта от класса C

Посмотрим в код. С одной стороны у нас один класс с приватными переменными и два класса: один однозначно пустой, а второй неопределённого состояния: ни то пустой, ни то с наследством. Несложно догадаться, что пустой у нас класс C , а вот класс B в неопределённом для многих из нас, новичков, состоянии. Чтобы проверить, были ли унаследованы поля, можно сравнить размеры классов. Если класс B не унаследовал ничего, то размер его будет равен размеру пустого класса, а если унаследовал, то размер его будет равен размеру класса A .

В зависимости от системы результаты на экран могут быть вывдены разные, но в любом случае получится, что A == B, а размер C скорее всего будет сильно меньше (в моём случае А==12, B==12, C==1). Это обозначает однозначно, что поля потомок к себе получил. Несмотря на то, что использовать мы их не можем, они в потомке оказались. Вот мы и проверили, что приватные поля наследуются, висят в памяти. А ещё можем сделать вывод, что кроме пожирания памяти и не делают ничего, и использовать их нельзя. Одним словом — Паразиты.

  • Приватные элементы наследуются. Хотя всё равно могут быть несогласные. Важно понимать, что под наследованием могут иметь в виду сам механизм наследования, а не получаемый от наследования эффект.
  • Конструкторы и деструкторы не наследуются.
  • Все перегруженные операции наследуются.
  • начиная С++11 конструкторы (с рядом исключений) можно наследовать явно, путем применения using-декларации.

C++. Модификаторы доступа private, protected, public. Инкапсуляция данных в классе

C++. Модификаторы доступа private , protected , public . Инкапсуляция данных в классе

Поиск на других ресурсах:

1. Случаи применения модификаторов доступа private , protected , public

Парадигма объектно-ориентированного программирования предусматривает возможность задания уровня доступности элементов классов. Уровень доступности позволяет регулировать доступ к данным и методам класса. Одни элементы класса могут быть общедоступны, другие — скрыты. Сокрытие данных и методов в классе называется инкапсуляцией.

В языке C++ уровень доступности определяется с помощью специальных модификаторов private , protected , public . Применение этих модификаторов может быть использовано в двух случаях:

  • в случае объявления элементов класса. Этот случай рассматривается в данной теме;
  • в случае наследования классов. Более подробно о применении модификаторов доступа при наследовании классов можно посмотреть здесь .
2. Применение модификаторов доступа для элемента класса
2.1. Модификатор доступа private . Особенности использования

Если в классе объявляется элемент (функция, член данных) в разделе private , то для него действуют следующие правила доступа:

  • элемент недоступен любым экземплярам методов других классов или методов, которые не есть «дружественными» к класу (рисунок 1);
  • элемент недоступен из унаследованных классов (рисунок 2);
  • элемент доступен из методов, которые реализованы в классе (рисунок 3);
  • элемент доступен из дружественных функций (рисунок 4);
  • элемент доступен из методов дружественных классов (рисунок 5).

C++. Модификатор доступа private. Нет доступа из экземпляра класса к private-элементу класса

Рисунок 1. Модификатор доступа private . Нет доступа из экземпляра класса к private -элементу value класса

C++. Модификатор доступа private. Нет доступа к private-элементу класса из унаследованного класса

Рисунок 2. Модификатор доступа private . Нет доступа к private -элементу класса из унаследованного класса

C++. Модификатор доступа private. Доступ к элементу класса из внутреннего метода класса

Рисунок 3. Модификатор доступа private . Доступ к элементу класса из внутреннего метода класса

C++. Модификатор доступа private. Доступ к элементу класса из дружественной функции (метода)

Рисунок 4. Модификатор доступа private . Доступ к элементу класса из дружественной функции (метода)

Если в коде, изображенном на рисунке 4, в объявлении класса A перед именем функции SetValue() убрать ключевое слово friend , то доступа к переменной value класса не будет. Как результат, в функции SetValue() в строке

objA.value = 33;

компилятор будет выдавать ошибку наподобие

Member A::value is inaccessible

C++. Модифікатор доступа private. Доступ к private-элементу класса из метода дружественного класса

Рисунок 5. Модификатор доступа private . Доступ к private -элементу класса из метода дружественного класса

2.2. Модификатор доступа public . Особенности использования

Если в классе определен элемент с модификатором доступа public , в этом случае справедливо правило:

  • элемент доступен всем методам в программе.

Исключение составляет случай, когда клас унаследован как private . Тогда даже public-элементы этого класса будут недоступны в унаследованных классах. Более подробно об использовании модификаторов доступа для класса можно прочитать здесь .

С++. Модификатор доступа public. Доступ к элементу класса из любого метода в программе

Рисунок 6. Модификатор доступа public . Доступ к элементу класса из любого метода в программе

С++. Модификатор доступа public. Доступ из унаследованного класса

Рисунок 7. Модификатор доступа public . Доступ из унаследованного класса

2.3. Модификатор доступа protected . Особенности применения

Модификатор доступа protected актуален в случаях, когда классы образуют иерархию наследования. Если в классе объявлен элемент (функция, член данных) с модификатором доступа protected , то для него действуют следующие правила:

  • элемент класса недоступен из любого внешнего метода (рисунок 8) если этот метод не является дружественным;
  • элемент класса доступен из внутренних методов класса (рисунок 8). Здесь следует заметить, что protected -элемент класса также доступен из экземпляра класса, если этот экземпляр объявляется во внутреннем методе класса;
  • элемент класса доступен из дружественных функций класса (рисунок 9);
  • элемент класса доступен из методов дружественного класса (рисунок 9);
  • элемент класса доступен из методов унаследованного класса (рисунок 10);
  • элемент класса недоступен из экземпляров унаследованного класса (рисунок 11). Это правило не касается «дружественных» методов и методов «дружественных» классов.

C++. Модификатор доступа protected. Нет доступа из экземпляра класса, если этот экземпляр создан в

Рисунок 8. Модификатор доступа protected . Нет доступа из экземпляра класса, если этот экземпляр создан в «недружественном» методе

На рисунке 8 продемонстрованы два вида доступа к protected -элементу класса:

  • через экземпляр (объект) класса, который объявляется во внутреннем методе класса Method() ;
  • непосредственный доступ как к члену данных класса.

C++. Модификатор доступа protected. Доступ из

Рисунок 9. Модификатор доступа protected . Доступ из «дружественных» методов и методов «дружественных» классов

C++. Модификатор доступа protected. Доступ из методов унаследованного класса

Рисунок 10. Модификатор доступа protected . Доступ из методов унаследованного класса

C++. Модификатор доступа protected. Нет доступа из экземпляров унаследованного класса

Рисунок 11. Модификатор доступа protected . Нет доступа из экземпляров унаследованного класса

Связанные темы

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *