개인 및 보호 회원 : C ++


276

누군가 수업 시간에 회원 private과 의 차이점에 대해 깨달을 수 있습니까 protected?

모범 사례 규칙에서 클래스 외부에서 호출되지 않은 변수와 함수를 만들어야 private하지만 내 MFC 프로젝트를 보면 MFC 가 선호하는 것으로 알고 있습니다 protected.

차이점은 무엇이고 어떤 것을 사용해야합니까?

답변:


374

개인 멤버는 자신을 정의하는 클래스 내에서만 액세스 할 수 있습니다.

보호 된 멤버는 멤버를 정의하는 클래스와 해당 클래스에서 상속 된 클래스에서 액세스 할 수 있습니다.

편집 : 둘 다 클래스의 친구들과 보호 멤버의 경우 파생 클래스의 친구들도 액세스 할 수 있습니다.

편집 2 : 문제의 맥락에서 의미가있는 것을 사용하십시오. 커플 링을 줄이고 기본 클래스의 구현을 보호 할 수있을 때마다 멤버를 비공개로 만들어야하지만 불가능한 경우 보호 멤버를 사용하십시오. 문제를 더 잘 이해하려면 C ++ FAQ 를 확인하십시오 . 보호 변수에 대한이 질문 도 도움이 될 수 있습니다.


12
C ++ FAQ 라이트에 대한 링크로 이동 한 isocpp.org/wiki/faq/basics-of-inheritance
애브너

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
파생 클래스는 기본의 개인 가상 함수를 재정의 할 수 있습니다
제임스 Hopkin에게

6

보호 멤버 변수 질문을 살펴보십시오 . class커플 링을 줄이려면 private을 기본값 (C ++ ses 처럼)으로 사용하는 것이 좋습니다 . 보호 된 멤버 변수는 항상 나쁜 생각입니다. 예를 들어 템플릿 메소드 패턴에 보호 된 멤버 함수를 사용할 수 있습니다.


웃긴, 나는 당신을보기 전에 내 게시물로 편집했습니다. Upvoted 때문에 같은 링크 :시 깃털 우연히 발견의 새
피 라스 Assaad

4

보호 된 멤버는 클래스의 자손과 동일한 모듈의 코드를 통해서만 액세스 할 수 있습니다. 비공개 멤버는 선언 된 클래스 및 동일한 모듈의 코드를 통해서만 액세스 할 수 있습니다.

물론 친구 기능은 이것을 창 밖으로 던져 버립니다.


4

비공개 멤버는 클래스 내에서만 액세스 할 수 있고 보호 멤버는 클래스 및 파생 클래스에서 액세스 할 수 있습니다. OO 언어의 상속 기능입니다.

상속 계층에서 액세스 할 수있는 파생 클래스를 결정하는 C ++에서 개인, 보호 및 공용 상속을 가질 수 있습니다. 예를 들어 C #에는 공용 상속 만 있습니다.


3

개인 = 모선 (기본 수업) 만 이용 가능 (예 : 부모님 만 부모님의 침실로 갈 수 있음)

보호 = 모선 (기본 수업) 및 딸이 접근 할 수 있음 (즉, 부모 만 부모의 침실로 갈 수 있지만 아들 / 딸이 부모의 침실로 들어가도록 허용 함)

공개 = 모선 (기본 수업), 딸 및 기타 모든 사람이 액세스 할 수 있음 (예 : 부모님 만 부모님의 침실에 들어갈 수 있지만 하우스 파티입니다-mi casa su casa)


2

파생 클래스에서 보호 된 멤버를 가져오고 업데이트하는 데 공용 멤버 함수가 필요하지 않기 때문에 코드의 효율성이 향상되고 작성해야하는 코드의 양이 줄어 듭니다. 그러나 파생 클래스의 프로그래머는 자신이하는 일을 알고 있어야합니다.


클래스 선언에서 구현 된 인라인 함수를 항상 사용할 수 있습니다. 컴파일러는이를 최적화합니다 (예를 들어 개인 멤버 변수에 대한 읽기 전용 액세스를 강제하는 좋은 방법 임).
Paul Sanders

2

private회원 데이터에 선호됩니다. C ++ 클래스의 멤버는private 기본적으로입니다.

public의견의 문제이지만 회원 기능에 선호됩니다. 최소한 일부 메소드에 액세스 할 수 있어야합니다. public모든 사람이 이용할 수 있습니다. 가장 유연한 옵션이며 가장 안전하지 않습니다. 누구나 사용할 수 있고 누구나 잘못 사용할 수 있습니다.

private전혀 접근 할 수 없습니다. 수업 밖에서도 사용할 수 없으며 오용 할 수 없습니다. 파생 클래스에는 없습니다.

protected파생 클래스에서 사용할 수 있기 때문에 타협입니다. 클래스에서 파생 될 때 기본 클래스에 대해 잘 이해하고 있으며 이러한 멤버를 오용하지 않도록주의해야합니다.

MFC 그것은 선호, 윈도우 API를위한 C ++ 래퍼 publicprotected. Visual Studio 마법사에 의해 생성 된 클래스 protected에는 public, 및 private멤버가 혼합되어 있습니다. 그러나 MFC 클래스 자체에는 몇 가지 논리가 있습니다.

같은 회원 SetWindowTextpublic종종 이러한 회원에게 액세스해야하기 때문입니다.

와 같은 멤버 OnLButtonDown는 창에서 수신 한 알림을 처리합니다. 액세스해서는 안되므로 protected. 파생 클래스에서 계속 액세스하여 이러한 함수를 재정의 할 수 있습니다.

일부 멤버는 스레드 및 메시지 루프를 수행해야하며 액세스하거나 재정의해서는 안되므로 다음과 같이 선언됩니다. private

C ++ 구조에서 public기본적으로 멤버가 있습니다. 구조체는 일반적으로 메서드가 아닌 데이터에만 사용되므로 public선언은 안전한 것으로 간주됩니다.


1
"C ++ 클래스의 멤버는 기본적으로 보호됩니다"라고 작성합니다. 표준에 따르면 정의 (14p3)에 사용 된 키워드에 따라 기본적으로 비공개 또는 공개 키워드입니다. Microsoft는 여기서 표준에서 벗어 납니까?
Alexander Klauer

@ AlexanderKlauer 틀 렸습니다 private. 기본적으로 Visual Studio에 있습니다. 그것은이다 private그것은 결코뿐만 아니라 GCC에서 기본적으로 public기본적으로. 내가 다시 틀리지 않는 한. 당신이 말하는 표준을 찾을 수 없습니다.
Barmak Shemirani

죄송합니다. 좀 더 구체적으로 말씀하셨습니다. 나는 C ++ 17 표준을 언급하고 있었다. C ++ 11 표준은 11p3에서 동일한 단어를 사용합니다. 답변을 업데이트 할 수 있습니까? 감사!
Alexander Klauer

1

비공개 멤버는 자신이 상속 한 클래스와 함께 선언 된 클래스에서 보호 멤버로 액세스 할 수있는 위치를 선언 한 동일한 클래스에서만 액세스 할 수 있습니다.


1
  • Private : 액세스 지정자입니다. 기본적으로 인스턴스 (멤버) 변수 또는 c ++ / java 클래스의 메소드는 개인용입니다. 상속하는 동안 코드와 데이터는 항상 상속되지만 클래스 외부에서는 액세스 할 수 없습니다. 데이터 멤버를 비공개로 선언하면 아무도 멤버 변수를 직접 변경할 수 없으며 비공개 멤버를 변경하기 위해 공개 게터 및 세터를 제공 할 수 있습니다. 이 개념은 항상 비즈니스 규칙에 적용됩니다.

  • 보호됨 : 액세스 지정자이기도합니다. C ++에서 보호 된 멤버는 클래스 내에서 상속 된 클래스에 액세스 할 수 있지만 클래스 외부에서는 액세스 할 수 없습니다. Java에서 보호 된 멤버는 클래스 내, 상속 된 클래스 및 동일한 패키지 내의 모든 클래스에 액세스 할 수 있습니다.


0

보호 된 비 정적 기본 클래스 멤버는 다음 중 하나를 사용하여 해당 기본 클래스에서 파생 된 클래스의 멤버 및 친구가 액세스 할 수 있습니다.

  • 직접 또는 간접적으로 파생 된 클래스에 대한 포인터
  • 직접 또는 간접적으로 파생 된 클래스에 대한 참조
  • 직접 또는 간접적으로 파생 된 클래스의 객체

0

개인 : 클래스 멤버 기능 및 친구 기능 또는 친구 클래스에서 액세스 할 수 있습니다. C ++ 클래스의 경우 이것이 기본 액세스 지정자입니다.

보호 : 클래스 멤버 함수, 친구 함수 또는 친구 클래스 및 파생 클래스에서 액세스 할 수 있습니다.

  • 클래스 멤버 변수 또는 함수 (typedef 또는 내부 클래스 포함)를 개인 또는 보호 요구 사항에 따라 보호 할 수 있습니다.
  • 대부분의 경우 클래스 멤버를 개인으로 유지하고 캡슐화 할 get / set 함수를 추가하십시오. 이것은 코드 유지 관리에 도움이됩니다.
  • 일반적으로 개인 함수는 공용 함수를 모듈 식으로 유지하거나 전체 코드를 단일 함수로 작성하는 대신 반복 코드를 제거하려는 경우에 사용됩니다. 이것은 코드 유지 관리에 도움이됩니다.

자세한 내용은이 링크참조하십시오 .


-2

개인 및 보호 된 액세스 수정자는 기본 클래스의 보호 된 멤버가 하위 (파생) 클래스의 기본 클래스 범위 밖에서 액세스 할 수있는 유일한 것입니다. 또한 상속에도 동일하게 적용됩니다. 그러나 전용 수정자를 사용하면 기본 클래스의 멤버는 기본 클래스의 범위 또는 코드에서만 액세스 할 수 있으며 그 친구 기능 만 가능합니다 '' ''


5
귀하의 답변이 다른 답변보다 어떤 가치를 더합니까?
Hermann Döppes
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.