Приватні та захищені члени: C ++


276

Чи може хтось просвітити мене щодо різниці між членами privateта protectedчленами занять?

Я розумію , від умовностей найкращої практики , що змінні і функції , які не називаються поза класом повинні бути зроблені private- але дивлячись на мій MFC проект, MFC , здається, користь protected.

У чому різниця і що я повинен використовувати?

Відповіді:


374

Приватні члени можуть бути доступні лише в класі, який їх визначає.

Захищені члени доступні в класі, який визначає їх, і в класах, які успадковують цей клас.

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

Редагування 2: Використовуйте все, що має сенс у контексті вашої проблеми. Ви повинні намагатися зробити членів приватними, коли ви можете зменшити з'єднання та захистити реалізацію базового класу, але якщо це неможливо, тоді використовуйте захищені члени. Перевірте C ++ FAQ для кращого розуміння проблеми. Це питання щодо захищених змінних також може допомогти.


12
Посилання на C ++ FAQ Lite перейшло на isocpp.org/wiki/faq/basics-of-inheritance
avner

134

Громадські члени класу A доступні для всіх і всіх.

Захищені члени класу A не доступні за межами коду A, але доступні з коду будь-якого класу, похідного від A.

Приватні члени класу A недоступні за межами коду A або коду будь-якого класу, похідного від A.

Отже, врешті-решт, вибір між захищеним чи приватним - це відповідь на наступні запитання: Скільки довіри ви готові вкласти програмісту похідного класу?

За замовчуванням припустіть, що похідному класу не слід довіряти, і зробіть своїх членів приватними . Якщо у вас є дуже вагомі причини надати доступ до внутрішніх класів материнських класів до похідних класів, тоді ви можете зробити їх захищеними.


Похідний клас повинен бути типом вашого класу, а захищені дані базового класу є частиною даних похідного класу. Очікується, що письменник похідного класу буде правильно обробляти ці дані або це помилка. Приватні дані в базовому класі - це те, що письменник похідного класу не контролює.
CashCow

@CashCow the protected data of the base class is part of the data of the derived class.Справді. Хіба не краще, щоб письменник похідного класу заявив, що дані у своєму класі замість моїх? ... :-) ... The writer of the derived class is expected to handle this data properly or it is a bug.У схемі NVI метою є зробити все приватним, у тому числі методів, щоб обмежити шкоду, яку може заподіяти письменник класу ієрархії. Захищені методи - це вже потенційна проблема. Я не впевнений, що посилення цього шляхом використання захищеної держави є правильним підходом.
paercebal

Це могло б вимагати, щоб у базовому класі були віртуальні «геттери», щоб отримати доступ до нього. І хоча ви можете мати між ними заняття, щоб виконувати різні способи реалізації шаблону даних, це не завжди практично. Наприклад, "шаблон", поширений у мовах, які не мають модифікатора "const", хоча і не потрібен більшу частину часу в C ++, - це мати базовий клас для читання і класи, що записуються. У C ++ це також може бути приємно просто тому, що вам потрібно більше, ніж один із можливих способів завантаження (ініціалізації) даних.
CashCow

Існують різні способи зробити це. Створіть друзів на уроках серіалізації. Покладіть всі свої дані до структури з загальнодоступним доступом, але ваш клас має приватного члена цієї змінної .... Захищені члени та похідні класи для завантаження їх з будь-якого джерела іноді простіше.
CashCow

63

До захищених членів можна отримати доступ із похідних класів. Приватні не можуть.

class Base {

private: 
  int MyPrivateInt;
protected: 
  int MyProtectedInt;
public:
  int MyPublicInt;
};

class Derived : Base
{
public:
  int foo1()  { return MyPrivateInt;} // Won't compile!
  int foo2()  { return MyProtectedInt;} // OK  
  int foo3()  { return MyPublicInt;} // OK
};‌‌

class Unrelated 
{
private:
  Base B;
public:
  int foo1()  { return B.MyPrivateInt;} // Won't compile!
  int foo2()  { return B.MyProtectedInt;} // Won't compile
  int foo3()  { return B.MyPublicInt;} // OK
};

З точки зору "найкращої практики" це залежить. Якщо є навіть слабка можливість, що хтось може захотіти вивести новий клас із наявного та потребувати доступу до внутрішніх членів, зробіть їх захищеними, а не приватними. Якщо вони приватні, ваш клас може легко важко успадкувати.


3
Я прошу відрізнятись: якщо є слабка можливість, що жоден підклас не потребує цього, зробіть його приватним. Якщо ви не збираєтесь підкласирувати свій клас, використовуйте шаблон шаблону методу.
xtofl

23

Причина того, що MFC надає перевагу захищеному, полягає в тому, що це рамка. Ви, мабуть, хочете підкласифікувати класи MFC, і в цьому випадку потрібен захищений інтерфейс для доступу до методів, не видимих ​​для загального використання класу.


9

Все залежить від того, що ви хочете зробити, і що ви хочете, щоб отримані класи могли бачити.

class A
{
private:
    int _privInt = 0;
    int privFunc(){return 0;}
    virtual int privVirtFunc(){return 0;}
protected:
    int _protInt = 0;
    int protFunc(){return 0;}
public:
    int _publInt = 0;
    int publFunc()
    {
         return privVirtFunc();
    }
};

class B : public A
{
private:
    virtual int privVirtFunc(){return 1;}
public:
    void func()
    {
        _privInt = 1; // wont work
        _protInt = 1; // will work
        _publInt = 1; // will work
        privFunc(); // wont work
        privVirtFunc(); // wont work
        protFunc(); // will work
        publFunc(); // will return 1 since it's overridden in this class
    }
}

6

Атрибути та методи, позначені як protectedтакі - на відміну від приватних - все ще помітні в підкласах.

Якщо ви не хочете використовувати або не надавати можливість змінити метод у можливих підкласах, я б їх створив private.


2
Похідний клас може перекрити приватні віртуальні функції своєї бази
Джеймс Хопкін

6

Впевнені, подивіться на питання щодо змінних захищених членів . Для classзменшення з'єднання рекомендується використовувати приватне як за замовчуванням (як це роблять C ++ ). Змінні захищених членів - це завжди погана ідея, захищені функції членів можуть використовуватися, наприклад, шаблон шаблону методу.


Смішно, я відредагував це на своєму дописі, перш ніж побачив ваше. Оголошено, тому що пташине перо натрапляє на одне посилання :)
Фірас Ассад

4

До захищених членів можуть звертатися лише нащадки класу та за кодом у тому ж модулі. Доступ до приватних членів може здійснюватися лише класом, в якому вони оголошені, та кодом у тому ж модулі.

Звичайно, функції друзів кидають це у вікно, але так добре.


4

приватні члени доступні лише з класу, захищені члени доступні в класі та похідні класи. Це особливість успадкування в мовах ОО.

Ви можете мати приватне, захищене та публічне успадкування в C ++, що визначатиме, до яких похідних класів можна отримати доступ в ієрархії спадкування. Наприклад, C # має лише державну спадщину.


3

приватний = доступний лише материнським (базовий клас) (тобто тільки мій батько може зайти в спальню мого батька)

захищена = доступна материнством (базовий клас) та її дочками (тобто лише мій батько може зайти в спальню мого батька, але дав синові / дочці дозвіл ходити в спальню батьків)

громадський = доступний материнством (базовий клас), дочкою та всіма іншими (тобто лише мій батько може зайти в спальню мого батька, але це домашня вечірка - mi casa su casa)


2

Оскільки жодна функція публічного члена не потрібна для отримання та оновлення захищених членів у похідному класі, це підвищує ефективність коду і зменшує кількість коду, який нам потрібно написати. Однак програміст похідного класу повинен знати про те, що він робить.


Ви завжди можете використовувати вбудовану функцію, реалізовану в декларації класу. Компілятор оптимізує це (наприклад, це був би хороший спосіб застосувати доступ лише для читання до змінної приватного члена).
Пол Сандерс

2

privateє кращим для даних членів. Учасники класів C ++ privateза замовчуванням.

publicє кращим для функцій членів, хоча це питання думки. Принаймні деякі методи повинні бути доступними. publicє доступним для всіх. Це найбільш гнучкий варіант і найменш безпечний. Користуватися ними може будь-хто, і будь-хто може ними неправильно користуватися.

privateвзагалі недоступний. Ніхто не може використовувати їх поза класом, і ніхто не може ними зловживати. Навіть у похідних класах.

protectedє компромісом, оскільки його можна використовувати у похідних класах. Коли ви виходите з класу, ви добре розумієте базовий клас, і ви обережні, щоб не зловживати цими членами.

MFC - це обгортка C ++ для API Windows, він вважає за краще publicіprotected . Класи , створювані Visual Studio Wizard мають потворну суміш protected, publicі privateчленів. Але в самих класах MFC є певна логіка.

Члени, такі як SetWindowText , publicтому що вам часто потрібно звертатися до цих членів.

Члени, такі як OnLButtonDown , обробляють сповіщення, отримані у вікні. До них не слід звертатися, тому вони є protected. Ви все одно можете отримати доступ до них у похідному класі, щоб змінити ці функції.

Деякі учасники повинні робити нитки та петлі повідомлень, до них не можна звертатись та не змінювати, тому вони оголошуються як private

У структурах C ++ учасники publicза замовчуванням. Структури зазвичай використовуються лише для даних, а не для методів, тому publicдекларування вважається безпечним.


1
Ви пишете "Члени класів C ++ захищені за замовчуванням". Відповідно до стандарту вони за замовчуванням є приватними або загальнодоступними, залежно від того, яке ключове слово було використано у визначенні (14p3). Microsoft відхиляється від стандарту тут?
Олександр Клауер

@AlexanderKlauer Я помилився, це privateза замовчуванням у Visual Studio. Це також privateза замовчуванням в gcc, а також ніколи publicза замовчуванням. Якщо я знову не помиляюся. Я не можу знайти стандарт, на який ви посилаєтесь.
Бармак Шемірані

Вибачте, я повинен був бути більш конкретним. Я мав на увазі стандарт C ++ 17. Стандарт C ++ 11 має таке ж формулювання у 11p3. Чи можете ви оновити свою відповідь? Дякую!
Олександр Клауер

1

Доступ до приватного члена можна отримати лише в тому ж класі, де він оголосив, де до захищеного члена можна отримати доступ до класу, де він оголошений разом з класами, які він успадковує.


1
  • Приватний : це специфікатор доступу. За замовчуванням змінні екземпляра (член) або методи класу в c ++ / java є приватними. Під час успадкування код і дані завжди успадковуються, але не є доступними поза класом. Ми можемо оголосити своїх членів даних приватними, щоб ніхто не міг вносити прямі зміни до змінних наших членів, і ми можемо надавати загальнодоступні користувачі та сетери з метою зміни наших приватних членів. І ця концепція завжди застосовується в бізнесі.

  • Захищено : це також специфікатор доступу. У C ++ захищені члени доступні в межах класу та до спадкового класу, але не за межами класу. У Java захищені члени доступні в межах класу, до успадкованого класу, а також до всіх класів в одному пакеті.


0

До захищеного нестатичного члена базового класу можуть звертатися члени та друзі будь-яких класів, що походять із цього базового класу, використовуючи одне з наступного:

  • Вказівник на прямо чи опосередковано похідний клас
  • Посилання на прямий або опосередкований похідний клас
  • Об'єкт класу, що походить прямо чи опосередковано

0

Приватний: Доступний для функцій членів класу та функції друзів або класу друзів. Для класу C ++ це специфікатор доступу за замовчуванням.

Захищений: Доступний для функцій членів класу, функції друзів або класу друзів та похідних класів.

  • Ви можете зберігати змінну або функцію члена класу (навіть typedefs або внутрішні класи) як приватну або захищену відповідно до вашої вимоги.
  • Більшу частину часу ви зберігаєте учасника класу як приватного та додаєте функції get / set для інкапсуляції. Це допомагає у підтримці коду.
  • Зазвичай приватна функція використовується, коли ви хочете зберігати свої публічні функції модульними або для усунення повторного коду замість того, щоб записувати весь код в одну функцію. Це допомагає у підтримці коду.

Перейдіть за цим посиланням для більш детальної інформації.


-2

приватні та захищені модифікатори доступу - це одне і те ж, що до захищених членів базового класу можна отримати доступ поза межами базового класу в дочірньому (похідному) класі. Це ж стосується і спадкування. Але за допомогою приватного модифікатора доступ до членів базового класу може бути доступний лише в області дії або коду базового класу, а лише його функції функціонують '' ''


5
Яке значення додає ваша відповідь над іншими відповідями?
Герман Дьоппес
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.