Перейти к содержимому

Protected c что это

  • автор:

protected (C++)

Ключевое слово protected указывает доступ к членам класса в списке членов до следующего описателя доступа ( public или) или private конца определения класса. Члены класса, объявленные как protected можно использовать только следующим образом:

  • Функции-члены класса, который изначально объявил эти элементы.
  • Дружественные элементы класса, который изначально объявил эти элементы.
  • Классы, производные с использованием открытого или защищенного доступа от класса, который изначально объявил эти элементы.
  • Прямые производные с использованием закрытого доступа классы, которые также имеют закрытый доступ к защищенным элементам.

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

Защищенные члены не так закрыты private , как члены, которые доступны только членам класса, в котором они объявлены, но они не являются общедоступными public , как члены, которые доступны в любой функции.

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

Специально для /clr

В типах СРЕДЫ CLR описатель доступа C++ ключевое слово ( public , private и protected ) может повлиять на видимость типов и методов в отношении сборок. Дополнительные сведения см. в разделе «Члены контроль доступа».

Файлы, скомпилированные с помощью /LN , не влияют на это поведение. В этом случае все управляемые классы (открытые или закрытые) будут видны.

КОНЕЦ специально для /clr

Пример

// keyword_protected.cpp // compile with: /EHsc #include using namespace std; class X < public: void setProtMemb( int i ) < m_protMemb = i; >void Display() < cout protected: int m_protMemb; void Protfunc() < cout > x; class Y : public X < public: void useProtfunc() < Protfunc(); >> y; int main() < // x.m_protMemb; error, m_protMemb is protected x.setProtMemb( 0 ); // OK, uses public access function x.Display(); y.setProtMemb( 5 ); // OK, uses public access function y.Display(); // x.Protfunc(); error, Protfunc() is protected y.useProtfunc(); // OK, uses public access function // in derived class >

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#)

Все типы и члены типов имеют уровень доступности. Он определяет возможность их использования из другого кода в вашей или в других сборках. Сборка — это DLL или EXE-файл, созданный путем компиляции одного или нескольких CS-файлов в одной компиляции. Следующие модификаторы доступа позволяют указать доступность типа или члена при объявлении:

  • public: тип или член можно получить к любому другому коду в той же сборке или другой сборке, которая ссылается на нее. Уровень доступности общедоступных элементов типа определяется уровнем доступности самого типа.
  • private: тип или член можно получить только по коду в том же class или struct .
  • защищенный: к типу или члену можно обращаться только по коду в том же class коде или в class производном от него class .
  • internal: тип или член можно получить к любому коду в одной сборке, но не из другой сборки. Другими словами, internal доступ к типам или элементам можно получить из кода, который является частью той же компиляции.
  • защищенный внутренний: к типу или члену можно получить доступ к любому коду в сборке, в которой она объявлена, или из производной class в другой сборке.
  • private protected: доступ к типу или элементу возможен из типов, производных от объекта class и объявляемых в сборке, содержащей этот объект.

Сводная таблица

Расположение вызывающего объекта public protected internal protected internal private protected private
В классе ✔️️ ✔️ ✔️ ✔️ ✔️ ✔️
Производный класс (та же сборка) ✔️ ✔️ ✔️ ✔️ ✔️ ❌
Непроизводный класс (та же сборка) ✔️ ✔️ ❌ ✔️ ❌ ❌
Производный класс (другая сборка) ✔️ ✔️ ✔️ ❌ ❌ ❌
Непроизводный класс (другая сборка) ✔️ ❌ ❌ ❌ ❌ ❌

В следующих примерах показано, как изменить модификаторы доступа для типа или члена типа:

public class Bicycle < public void Pedal() < >> 

Не все модификаторы доступа подходят для всех типов или членов во всех контекстах. В некоторых случаях доступность члена типа ограничивается доступностью содержащего его типа.

Доступность классов, записей и структур

Классы, записи и структуры, объявленные непосредственно в пространстве имен (другими словами, не вложенные в другие классы или структуры), могут быть public или internal . Если модификатор доступа не указан, по умолчанию используется internal .

Члены структуры, включая вложенные классы и структуры, могут быть объявлены как public , internal или private . Члены класса, включая вложенные классы и структуры, могут быть public , protected internal , protected , internal , private protected или private . Члены класса и структуры, включая вложенные классы и структуры, по умолчанию имеют доступ private . Закрытые вложенные типы недоступны за пределами типа, в котором содержатся.

Производные классы записи не могут быть более доступными, чем соответствующие базовые типы. Невозможно объявить открытый класс B , производный от внутреннего класса A . Если бы это было возможно, класс A стал бы открытым, так как все члены protected или internal класса A были бы доступны из производного класса.

Доступ к внутренним типам можно предоставить некоторым другим сборкам с помощью InternalsVisibleToAttribute . Дополнительные сведения см. в разделе Дружественные сборки.

Доступность членов классов, записей и структур

Члены классов и записей (включая вложенные классы, записи и структуры) можно объявлять с любым из шести типов доступа. Члены структуры не могут быть объявлены как protected , protected internal или private protected , так как структуры не поддерживают наследование.

Как правило, уровень доступности члена не может быть выше уровня доступности типа, в который он входит. При этом член public внутреннего класса может быть доступен за пределами сборки, если он реализует методы интерфейса или переопределяет виртуальные методы, определенные в открытом базовом классе.

Тип любого поля, свойства или события члена должен иметь по меньшей мере такой же уровень доступности, как у самого члена. Точно так же тип возвращаемого значения и типы параметров любого метода, индексатора или делегата должен иметь по меньшей мере такой же уровень доступности, как у самого члена. Например, невозможно иметь метод public M , возвращающий класс C , если только C также не является public . Аналогичным образом, невозможно иметь свойство protected типа A , если A объявлен как private .

Пользовательские операторы всегда должны объявляться как public и static . Для получения дополнительной информации см. раздел Перегрузка операторов.

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

Чтобы настроить уровень доступа для члена class , record или struct , добавьте в объявление этого члена соответствующее ключевое слово, как показано в следующем примере.

// public class: public class Tricycle < // protected method: protected void Pedal() < >// private field: private int _wheels = 3; // protected internal property: protected internal int Wheels < get < return _wheels; >> > 

Другие типы

Интерфейсы, объявляемые непосредственно в пространстве имен, могут быть public или internal . Как и в случае с классами и структурами, для интерфейсов по умолчанию задается доступ internal . Члены интерфейса по умолчанию являются public , так как интерфейс как раз и создан для того, чтобы обеспечить другим типам доступ к классу или структуре. Объявления членов интерфейса могут включать любой модификатор доступа. Это удобнее всего использовать для статических методов, чтобы предоставить общие реализации, необходимые всем объектам, реализующим класс.

Члены перечисления всегда являются public , и модификаторы доступа к ним не применяются.

Делегаты ведут себя как классы и структуры. По умолчанию они имеют доступ internal , если объявляются непосредственно в пространстве имен, и доступ private , если являются вложенными.

Сводная таблица доступа по умолчанию

Тип Доступ по умолчанию
class internal
struct internal
interface internal
record internal
enum internal
interface Членов public
Анонимные типы internal
члены класса, записи и структуры private

Спецификация языка C#

Дополнительные сведения см. в спецификации языка C#. Спецификация языка является предписывающим источником информации о синтаксисе и использовании языка C#.

См. также

  • Укажите порядок модификаторов (правило стиля IDE0036)
  • Руководство по программированию на C#
  • Система типов C#
  • Интерфейсы
  • Уровни доступности
  • private
  • public
  • internal
  • protected
  • protected internal
  • private protected
  • sealed
  • class
  • struct
  • interface
  • Анонимные типы

Совместная работа с нами на GitHub

Источник этого содержимого можно найти на GitHub, где также можно создавать и просматривать проблемы и запросы на вытягивание. Дополнительные сведения см. в нашем руководстве для участников.

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): Переформатировал исходный код под использование встроенного плагина вордпресса.

Поделиться ссылкой:

Нравится Загрузка.

Похожее

31 комментарий

Табуляцая съехала, трудно читать примеры. Поправь, если не тяжело.
Сергей, спасибо, поправил.

Фигассе отжиг, афтор �� Новичкам очень полезно знать, как убить и без того кривой ООП в с++, это вы правильно подметили.
За идею корежить private поля убить-убить-убить РЖАВОЙ СЕКИРОЙ УЖОСА =). С наилучшими, Meowth.

meowth, �� Улыбнуло

Взломы для доступа к private стоит все-таки убрать, наверное, действительно. И еще, тяжело код читать, стоит подправить стили. Firefox 3b5

Alno, у меня Opera, всё хорошо отображает. Может, в FF3 проблема? А насчёт убрать, не согласен. Зачем закрывать доступ к информации? Я же не пропагандирую постоянно писать в таком стили, но может сложиться ситуация, когда иного пути просто не будет.

Все, вспомнил;) Меня долго мучало ощущение дежавю — где-то я такое уже читал. И вот я вспомнил — это примеры с книги Herb Sutter «Exceptional C++ Style». Я прав?

Сергей, действительно так. Думаю, что и в других источниках (и в книгах и в сети) можно найти эту информацию.

Мощная книга, кстати. Взламывает наивные представления о возможности языка С++
Сергей, для меня такими «взломщиками» стали Элджер и Александреску ��
аффтар аццкий хакир
самая смешная статья по С++ которую я когда-либо читал
Torvin, а что конкретно насмешило?

в С++ нет средств для защиты кода. это логично, поскольку С/С++ — никсовые детища. чтобы распространять даже скомпиленную либу, нужно предоставить заголовочный файл с определением всех классов, который с легкостью подвергается изменению (которое в любом случае необходимы для способов 1-2). таким образом если нужно добраться до закрытого члена даже класса из сторонней библиотеки — сделать это не представляет сложности.
а все потому, что модификаторы доступа служат не для «защиты» каких-то «секретных» частей кода, а _исключительно_ для защиты от программистких ошибок. т.е. для инкапсуляции. в тех же целях добавлен модификатор const. автор похоже этого не понимает… единственную практическую ценность представляет лишь способ 3 с reinterpret_cast который пригодится в случае с чем-то вроде COM. и к С++ напрямую не имеет никакого отношения. P.S.
#define private public жжот. надеюсь вы это не в серьез

Вот я б не смог лучше написать))) Формулировка «секретные части кода» просто в пятерку))

Torvin, спасибо за ответ. Автор понимает для чего служат модификаторы доступа. Тем не менее, в результате совокупного действия разных факторов у вас на руках может оказаться библиотека без исходных кодов, с которой придётся проделать операцию описанную в этой заметке. Дай бог, чтобы этого с вами не случилось ��

вот я и говорю что не бывает C++ библиотеки без заголовочного файла. в котором можно любые private-мемберы исправить на public.
где вы такую библиотеку видели.

Torvin, исправить-то можно, только потом можно поиметь проблемы с линкером, если он имена для public и private членов по-разному преобразует.

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

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