Приватні та захищені члени: 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.