2011-01-13 4 views
3

public이어야하는 중첩 클래스가 C++로 있습니다. 그러나 나는 바깥 세상에 보이는 몇 가지 메소드를 필요로하고 나머지는 중첩 클래스에 만 볼 수 있습니다. 즉,public 중첩 클래스의 일부를 중첩 클래스에만 표시

class set { 
public: 
    class iterator { 
     innerMethod(); 
    public: 
     outerMethod(); 
    } 
} 

innerMethod()를 사용하는 set 메소드를 작성하고 싶습니다. 공개하는 경우 외부에서도 액세스 할 수 있습니다. 이는 내가 원하지 않는 것입니다. "친구 클래스 집합"을하지 않고 그것을 할 수있는 방법이 있습니까?

미리 감사드립니다.

+4

왜 'friend' 선언을 사용하지 않으시겠습니까? – finnw

+0

당신이 인용 부호로 "친구 클래스 집합"이라고 부르는 이유는 확실치 않습니다. 그냥 분명히하기 위해서, 당신은 당신을 괴롭히지 않는'public'과 똑같은 방법으로'friend'를 사용할 수 있습니다. –

+2

이것은 정확히 'friend' 선언이 캡슐화를 향상시키는 경우와 같습니다. 명백한 대안은 캡슐화를 완전히 중단하기 때문입니다. – aschepler

답변

1

아니요, 저는 해커가 아닌 다른 방법이 있다고 생각하지 않지만 friend 지시문을 사용한다고 생각하지 않습니다.

이 이런 종류의 목적에 적합합니까? 왜 이것을 피합니까?

+0

내가 현재 가지고있는 프로그래밍 수업에서 '친구'를 사용하는 것은 주변에 다른 방법이 없다면 일반적으로 "나쁜 프로그래밍"으로 간주되며 일반적으로 "나쁜 프로그래밍"으로 간주됩니다. 그래서 나는 가능한 한 그것을 피하려고 노력한다. – Mockingbird

+0

@Mokingbird :'friend'는 캡슐화를 깨뜨 렸습니다. 아마도 선생님이 나쁜 스타일이라고 말한 이유 일 수 있습니다. 그러나 멤버 함수가 캡슐화를 깨뜨린 이유는 무엇입니까? – Nawaz

+1

@Mokingbird : 질문 할 좋은 기회 인 것 같습니다. 나는 왜 누군가가 '친구'가 * 나쁜 프로그래밍 습관이라고 말하는지 궁금하다. 분명히, 다른 것과 마찬가지로 분명히 잘못 인식 된 객체 지향 디자인을 사용하는 것보다주의해서 사용해야하지만, 필요할 때 사용할 때 본질적으로 잘못된 것은 없습니다. 또한 [C++ FAQ on'friend'] (http://www.parashift.com/c++-faq-lite/friends.html)를 참조하십시오. –

1

질문 : 추가하지 않고 두 개의 숫자를 추가 할 수있는 방법이 있습니까? 내가 거친 해요 경우 미안 하지만 친구 클래스이 정확히입니다 ...

+0

예, 비트 연산자를 사용할 수 있습니다. 나쁜 예. ;-) –

2

friend 키워드를 사용하지 않고이 작업을 수행 할 수있는 좋은 방법이 없다. 주석에서

당신이 말한 : 나는 현재 걸릴 프로그래밍 클래스에서

될 것이라고했다 '친구'를 사용 대부분의 경솔한 일반적으로 "나쁜 프로그램"으로 간주, 이 실제로 없다면 을 사용하십시오. 그래서 나는 가능한 한 많이 으로 피하려고합니다. 수업 선생님이 나쁜 프로그래밍 말했습니다 이유

friend 휴식 캡슐은, 아마도 그 이유입니다. 그러나 멤버 함수가 캡슐화를 너무 깨뜨린 경우 왜 사용합니까? 왜 그들을 피하지 않을까요? friend은 member-functions와 같은 방식으로 캡슐화를 중단합니다.이므로 회원 기능 을 사용할 때 편리하면이 필요하므로 friend일 때 편안해야합니다. 둘 다 C++에 존재합니다!

class set { 
public: 
class iterator 
{ 
    friend class set; //<---- this gives your class set to access to inner methods! 

    void innerMethod(){} 
public: 
    void outerMethod(){} 
}; 
iterator it; 

void fun() 
{ 
    it.innerMethod(); 
    it.outerMethod(); 
} 
}; 

이 참조 : How Non-Member Functions Improve Encapsulation

+1

나는 아무런 말도하지 않습니다. 오히려 "더 쉽지 않습니다"... 나는 방법을 비공개로 설정할 수 있고, 친구를 사용하지 않으며 그럼에도 불구하고 그것을 호출 할 수 있습니다. 외부 클래스.하지만 확실히 좋은 생각이 아닐 것입니다 ... – ds27680

+0

사실 그것은 비교적 기밀이지만, 나는 이미 몇 번 옹호 해왔다. 그래서. 중첩 클래스에만 국한되지는 않습니다. Proxys 또는 Advocate 패턴과는 조금 다른 Keys의 사용법을 설명하는 맨 위에 더 가까이 갈 수있는 답변을 추가했습니다. –

+0

캡슐화의 요점은 사용자가 클래스를 사용하는 것을 방지하는 것이 아니라 클래스 멤버에 대한 제어 된 액세스 권한을 부여하는 것입니다. 또한이를 위해 미리 정의 된 함수/메소드 집합을 제공합니다. 사용자가 아닙니다. 예 : 합리적인 수의 클래스에서 사용자가 분모에 직접 액세스하는 것을 방지하고이 클래스의 사용자가 분모에서 0을 pt하려고 할 때 예외를 throw하는 계약자를 지정합니다. – Mockingbird

0

당신이 뭔가를 할 수 있습니다

클래스 설정

{

public: 
    class iterator 
    { 
     protected: 
      iterator(){}; 
      virtual ~iterator(){}; 

     public: 
      //outer world methods... 
    }; 

private: 
    class privateIterator : public iterator 
    { 
     public: 
      privateIterator(){}; 
      ~privateIterator(){} 

     //inner methods; 
    }; 

public: 
    iterator* CreateIterator() 
    { 
     return new privateIterator();//this is used to be sure that you only create private iterator instances 
    } 

};

옳은 답변인지는 모르겠지만 이제는 친구 키 작업을 사용하며 일부 방법은 숨 깁니다. 유일한 문제는 privateIterator를 선언 할 수없고 항상 CreateIterator를 사용하여 인스턴스를 만들어야한다는 것입니다.

1

예 있습니다.

나는 잠시 동안 방법을 옹호하려고 노력 해왔다. 기본적인 생각은 Key 클래스를 사용하는 것이다.

실제로는 이 아니지만 friend을 사용하면 노출 된 구현 세부 정보가 줄어 듭니다.

class set; 

// 1. Define the Key class 
class set_key: noncopyable { friend class set; set_key() {} ~set_key() {} }; 

class set 
{ 

    // 2. Define the iterator 
    class iterator 
    { 
    public: 
    void public_method(); 

    void restricted_method(set_key&); 

    }; // class iterator 

}; // class set 

이제 restricted_method 그래서 setiterator에 대한 특별한 접근을 필요로하지 않는다, public입니다. 그러나 그것의 사용은 set_key 인스턴스를 전달할 수있는 사람들로 제한되어 있으며 편리하게 set만이 그러한 객체를 만들 수 있습니다.

실제로 set은 신뢰하는 다른 사람에게 set_key 개체를 전달할 수 있습니다. 그것은 전통적인 의미의 열쇠입니다 : 누군가에게 평평한 열쇠를 주면 그것을 다른 사람에게 맡길 수 있습니다. 그러나 키 클래스의 의미 (복사 할 수 없기 때문에 set만이이를 생성하고 파기 할 수 있습니다) 이것은 일반적으로 key 개체의 범위 지속 기간으로 제한됩니다.

악의적 인 해킹은 항상 가능합니다. 즉 *((set_key*)0)입니다. 이 계획은 Machiavelli가 아닌 Murphy를 보호합니다 (C++에서는 불가능합니다).

관련 문제