같은 클래스의 개체가 서로의 개인 데이터에 액세스 할 수있는 이유는 무엇입니까?


98

같은 클래스의 개체가 서로의 개인 데이터에 액세스 할 수있는 이유는 무엇입니까?

class TrivialClass {
public: 
  TrivialClass(const std::string& data) :
    mData(data) {};

  const std::string& getData(const TrivialClass& rhs) const {
    return rhs.mData;
  };

private:
  std::string mData;
};

int main() {
  TrivialClass a("fish");
  TrivialClass b("heads");

  std::cout << "b via a = " << a.getData(b) << std::endl;
  return 0;
}

이 코드는 작동합니다. 객체 a가 객체 b의 개인 데이터에 액세스하고이를 반환하는 것은 완벽하게 가능합니다. 왜 그래야합니까? 개인 데이터는 비공개라고 생각합니다. (저는 pimpl 관용구에서 복사 생성자를 이해하려고 시도했지만이 간단한 상황을 이해하지 못했다는 것을 발견했습니다.)


18
글쎄요, 시작점으로, 가장 단순한 클래스 외에는 복사 생성자를 제대로 구현할 수 없습니다. 당신은 자신의 가장 좋은 것으로 클래스 생각할 수있는 친구 :-)
카메론

4
고객의 개인 정보를 생각하지만 클래스의 모든 직원은 액세스 권한이 있습니다
Martin Beckett 2011 년

고마워요 Cameron. 의미가 있지만 왜이 액세스가 복사 생성자와 할당 연산자로만 제한되지 않습니까?
Keith

5
같은 유형의 개체는 종종 많은 상호 작용을합니다. 그리고 아무도 다른 인스턴스의 개인 데이터를 전달하는 메서드를 작성하도록 강요하지 않습니다. :)
UncleBens

4
단순히 컴파일 타임에 컴파일러는 동일한 객체를 식별 할 방법이 없기 때문입니다. 이러한 액세스를 적용하려면 런타임 지원이 필요합니다.
Chethan 2013 년

답변:


80

그것이 C ++에서 작동하는 방식이기 때문입니다. C ++에서 액세스 제어는 개체 단위가 아닌 클래스 단위로 작동 합니다.

C ++의 액세스 제어는 정적 컴파일 타임 기능으로 구현됩니다. 컴파일 타임에 의미있는 객체 별 액세스 제어를 구현하는 것이 실제로 불가능하다는 것이 분명하다고 생각합니다. 이러한 방식으로 클래스 별 제어 만 구현할 수 있습니다.

개체 별 제어에 대한 몇 가지 힌트가 보호 액세스 사양에 나와 있기 때문에 표준 (11.5)에 자체 전용 장이 있습니다. 그러나 여전히 설명 된 개체 별 기능은 다소 초보적입니다. 다시 말하지만, C ++의 액세스 제어는 클래스별로 작동하도록되어 있습니다.


9
+1. C ++는 런타임 메커니즘이 아니라 컴파일 타임 메커니즘이 중요합니다. 꽤 좋은 일반 규칙.
Nemo

4
"컴파일 타임에 의미있는 객체 별 액세스 제어를 구현하는 것은 실제로 불가능합니다." 왜 안돼? 이어 void X::f(X&x), 컴파일러는 쉽게 구별 가능 this->a하고 x.a. 컴파일러가 알고하는 것이 (항상) 불가능 *this하고 x실제로 경우이 같은 객체 x.f(x)호출,하지만 난 아주 잘 언어 디자이너가이 확인을 찾아 볼 수 있었다.
André Caron 2011-08-03

@ AndréCaron 나는 이것이 실제로 훨씬 더 큰 물고기 주전자라고 생각합니다. 발생하지 않습니다 인라인 경우 컴파일러는 항상 여부를 확인해야 할 것 this&x동일합니다. 설상가상으로 이것은 X::f(Y& y)우리의 구체적인 객체가 와 Z둘 다에서 상속되는 유형일 수 있기 때문에 실제로에서도 문제가됩니다 . 요컨대 그것은 성능이 아니라 진짜 엉망이며 MI로 작업을 현명하게 만들기가 어렵습니다. XY
Nir Friedman

@NirFriedman 나는 당신이 제안을 오해한다고 생각합니다. 컴파일 할 때에 X::f(X& x)대한 액세스가 있으면 컴파일 x.a되지 않습니다. 다른 변경 사항은 없으며 검사를 삽입 할 필요가 없으므로 여전히 유효한 프로그램의 성능에 영향을주지 않습니다. 그리고 기존 C ++에 대한 획기적인 변경이 아니라 디자이너가 private원래 도입 할 때 할 수 있었던 일 입니다.
Alexey Romanov

31

"비공개"는 "내 사진을 볼 수 없도록 페이스 북에있는 내 사진을 비공개로 만들었다"는 의미에서 액세스 제어 메커니즘이 아닙니다.

C ++에서 "private"는 단순히 이것이 당신 (클래스의 코더)이 향후 버전 등에서 변경할 수있는 클래스의 일부라고 말하며, 클래스를 사용하는 다른 코더가 해당 클래스의 존재 또는 기능에 의존하는 것을 원하지 않습니다. .

진정한 액세스 제어를 원한다면 진정한 데이터 보안 기술을 구현해야합니다.


13

이것은 좋은 질문이며 최근에이 질문을 보았습니다. 동료들과 몇 가지 토론을했고 여기에 토론 요약이 있습니다. 이것은 의도적으로 설계된 것입니다. 이 디자인이 모든 경우에 완전히 합리적이라는 것을 의미하지는 않지만, 클래스 별 private이 선택되는 이유를 고려해야합니다. 우리가 생각할 수있는 가능한 이유는 다음과 같습니다.

우선, 인스턴스 당 액세스 제어 비용이 매우 높을 수 있습니다. 이것은이 스레드에서 다른 사람들에 의해 논의되었습니다. 이론적으로는 포인터 검사 를 통해 수행 할 수 있습니다 . 그러나 이것은 컴파일 타임에 수행 할 수 없으며 런타임에만 수행 할 수 있습니다. 따라서 런타임에 각 구성원의 액세스 제어를 식별해야하며 위반시 예외 만 발생합니다. 비용이 높습니다.

둘째, 클래스 별 액세스 제어에는 복사 생성자 또는 연산자 =와 같은 고유 한 사용 사례가 있습니다. 액세스 제어가 인스턴스 단위 인 경우 구현하기 어려울 것입니다.

또한 액세스 제어는 주로 데이터가 아닌 코드 / 멤버에 대한 액세스를 모듈화 / 제어하는 ​​방법에 대한 프로그래밍 / 언어 관점에서 이루어집니다.


12

이것은 임의의 언어 디자인 결정입니다. 예 를 들어 Ruby 에서 private실제로는 "인스턴스 만 자신의 개인 데이터 멤버에 액세스 할 수 있습니다"와 같이 개인을 의미합니다. 그러나 이것은 다소 제한적입니다.

주석에서 지적했듯이 복사 생성자와 할당 연산자는 다른 인스턴스의 개인 데이터 멤버에 직접 액세스하는 일반적인 위치입니다. 그 이유는 덜 분명합니다.

다음 경우를 고려하십시오. OO 연결 목록을 구현하고 있습니다. 연결 목록에는 포인터 관리를위한 중첩 노드 클래스가 있습니다. 이 노드 클래스를 구현하여 포인터 자체를 관리 할 수 ​​있습니다 (포인터를 공개하고 목록에서 관리하는 대신). 이 경우 일반적인 복사 생성자 및 할당 연산자가있는 다른 위치에서 다른 노드 개체의 포인터를 수정하려는 노드 개체가있을 것입니다.


4

트릭은 데이터가 기억하는 것입니다 private받는 클래스 가 아닌 경우 클래스의. 클래스 내의 모든 메서드는 해당 클래스의 모든 인스턴스의 개인 데이터에 액세스 할 수 있습니다. 다른 인스턴스의 비공개 데이터 멤버에 명시 적으로 액세스하는 메서드를 금지하지 않는 한 인스턴스 내에서 데이터를 비공개로 유지할 수있는 방법이 없습니다.


1

위의 모든 답변 외에도 사용자 정의 복사 생성자, 할당 연산자 및 다른 인스턴스에서 작동하는 클래스에 대해 작성하는 기타 모든 함수를 고려하십시오 . 모든 데이터 멤버에 대한 접근 자 함수가 필요합니다.


-8

개인 데이터는 액세스 권한이있는 누군가가 다른 사람에게 공개 할 때까지 비공개로 유지됩니다.

이 개념은 다음과 같은 다른 상황에도 적용됩니다.

class cMyClass
{
public:
   // ...
   // omitted for clarity
   // ...

   void Withdraw(int iAmount)
   {
      iTheSecretVault -= iAmount;
   }

private:
   int iTheSecretVault;
};

어떻게 돈을 인출 할 수 있습니까? :)


3
이 예제는 다른 인스턴스의 개인 데이터 멤버에 액세스하는 한 클래스 인스턴스를 포함하지 않습니다.
André Caron 2011-08-03

@Andre, "이 개념은 같은 ..., 너무 다른 상황에 적용"
YeenFei

^ "다른 상황"은 정의상 주제에서 벗어난 것이므로 귀하의 예는 관련성이 없습니다 (그리고 다른 곳에서도 유익 할 것 같지 않습니다)
underscore_d

1
이것은 질문에 대한 올바른 설명이 아닙니다.
Panda
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.