설명 -

friend 키워드는 c++에서 지원하는 예외적인 기능의 키워드다. 접근 지정자(Access Modifier)를 완벽히 무시할 수 있는 예외적인 기능을 가졌다. 객체 지향 개념의 정보 은닉(Information Hiding) 개념에 정면으로 위배된다.


기능 및 특징 - 

private 건 protected건 friend로 선언된 대상에게는 완벽하게 public으로 작용한다. 대상이 외부이건, 상속 관계도에 있건 그런 것은 중요치 않다.


friend 키워드는 특이하게도 '당하는' 쪽에서 선언한다. 


기존의 키워드 선언은 그것을 하려는 쪽에서 붙였었다. ex) static 선언시 해당 대상은 static 멤버가 된다. 반면 friend는 friend로 지정될 대상을 정하고, 그 내용을 자기 클래스 안 (혹은 함수) 에 선언한다.


 1. friend 지정은 단 방향이며 명시적으로 지정한 대상만 friend가 된다.
 2. friend 지정은 전이되지 않으며 friend의 friend 관계는 인정하지 않는다.
 3. 복수의 대상에 대해 동시에 friend를 지정할 수 있지만 한 번에 하나씩만 가능하다.
 4. friend 관계는 상속되지 않는다.


1번 - > 키워드를 선언한 객체에 대해서 선언 받은 대상은 얼마든지 접근할 수 있지만, 반대로 선언 받은 대상에 대해서 선언한 객체는 전혀 접근할 수 없다. ex) A가 B를 friend로 선언했다면, B는 A를 멋대로 쓸 수 있지만 A는 B에게 접근할 수 없다.

물론 friend 키워드는 서로 사용할 수 있으므로 A와 B가 서로 friend로 등록하면 A와 B 서로가 접근하는 것이 가능하다.


2번 , 4번 - > A가 B를 friend로 선언했어도, B의 friend인 C가 A를 건드릴 순 없다. 이는 상속관계에서도 마찬가지이다.


3번 - >  여러 객체에 대해 friend 선언할 수 있다. 다만 int a, b , c; 같은 선언은 지원 안함.


사용 방법 예시 및 이해도 -


friend 키워드를 사용하는 방안은 3가지다.

1. friend 클래스

2. friend 멤버 함수

3. friend 전역 함수


1. friend 클래스


- 특정 클래스 입장에서 다른 클래스를 자신의 친구(friend)로 선언하는 것. 대상에게 자신을 public처럼 인식될 수 있게 한다.


클래스 babo는 trash에게 friend를 선언하고 있다.




trash는 friend의 private 멤버인 money에 접근하여 값을 가져가버렸다.


하지만 만약 friend 선언을 안하면 어떻게 될까?



곧장 에러 처리된다. 접근할 권한이 없는 녀석이 접근 했기 때문이다.


위에서도 설명했듯이, babo가 trash를 friend 선언한 상태라고 해도 babo가 trash에 접근할 수는 없다.



2. friend 멤버 함수

- 클래스 전체가 아닌 클래스의 특정 멤버 함수만을 프렌드로 선언.

firend 클래스의 경우, A가 B를 friend 선언시, 난 B의 꺼야! 라고 하는 것으로 B의 모든 멤버 함수가 A에 간섭할 수 있는 반면, friend 멤버 함수 선언시, 난 B의 '멤버 함수' 꺼야! 라고 선언하는 것과 같다. 즉슨 B의 특정 멤버 함수만이 A를 간섭할 수 있고, 그 외의 멤버가 접근하려 들면 단호히 꺼지라고 하는 것.


바보의 하단에 trash의 sendCall 함수를 friend로 선언하고 있는 것을 볼 수 있다.

sendCall 함수를 보다 하단에 정의한 이유는, 그렇게 하지 않으면 컴파일러가 읽어들일 때 babo 객체의 내부구조를 볼 수 없어서 멤버를 건드릴 수 없기 때문이다.


이처럼 접근이 된다.


만약 그 함수가 아닌 짝퉁함수를 선언하여 접근하면 어떻게 될 까?


friend 멤버 함수 선언시 해당 함수가 아니면 접근이 불가능하다는 점을 명심하자.


3. friend 전역 함수

- private, protected 접근 지정자를 무시하고, 클래스 내부의 멤버에 접근할 수 있다.



friend 전역함수는 이와 같이 선언한다.




함수명에 friend 하나 붙였을 뿐인데, privater가 privateFunction을 걷어차버렸다!


이유는 더 이상 멤버가 아니기 때문이다! privateFunction 함수는 더 이상 privater의 소유물이 아닌 것이다.


friend 전역(external) 함수라고 불리우는 이유는 말 그대로 전역함수가 되어버렸기 때문이다. 따라서 아래와 같이 호출한다.



이와 같이 선언해야한다.


그러나 이처럼 선언하면 에러가 뜬다.



왜 일까? 싶지만.. 위에서도 설명했듯, '전역함수'가 되었다.

전역함수에 어떤 클래스인지도 모르는 놈의 멤버를 사용해라! 라고 하면.. 에러부터 내고 보는 것이 인지상정일 것이다. 따라서 아래처럼 수정하면 된다.



해당 class를 인자로 받아 아래와 같이 사용한다.

너무도 자연스럽게 사용해서 이상한 점을 못 느끼겠지만, 이 예제는 지금 private로 선언된 멤버에 외부에서 멋대로 접근하고 있다!


이는 연산자 오버로딩에 무척 중요한 가치를 가진다.


덧붙여 '전역' 함수라고 하였는데, 함수 내부에 선언되었을 뿐 전역적으로 아무에게나 접근이 가능하다. 딱히 대상을 가리지 않는다. 아래의 예제를 보자.




ㄴ 이와 같이 해도 정상적으로 접근된다.


장단점 및 비교 -

장점 :

1. 연산자 오버로딩 등 예외적인 경우 필요하다.

2. 클래스를 사용하는 측면에서 추가적인 함수(접근 함수)의 호출이 필요없으므로 나은 성능을 기대할 수 있다.

단점 :

1. 객체 지향 개념에서는 깽판 그 자체다.

2. 클래스 간의 의존도를 높인다. 유연한 코드가 아니게 된다.


첨부 자료 -

위의 내용들을 작성하면서 작성해보고, 사용한 예제이다. 필요한 사람이 혹여나 있을까 하여 올려둔다. 그게 내가 될 수도 있는 법이고.. 말이다.

friend 테스트.zip



참고한 주소 및 정보 -

http://warmz.tistory.com/890



Posted by GENESIS8

댓글을 달아 주세요

  1. jin 2016.09.30 11:28  댓글주소  수정/삭제  댓글쓰기

    궁금했던 키워드라 찾아봤는데 덕분에 잘 알고 갑니당!

  2. 요원009 2018.04.27 18:19 신고  댓글주소  수정/삭제  댓글쓰기

    훌륭한 예제네요. 감탄하고 갑니다 ㅎ

  3. 두들낙서 2019.12.13 16:27 신고  댓글주소  수정/삭제  댓글쓰기

    재미있고 명쾌한 설명 잘 보고 갑니다~