C ++ 친구에게 또는 친구에게


19

이번 학기에는 C ++ 과정을 사용한 객체 지향 프로그래밍이 있으며 친구 기능에 대해 배우고있었습니다.

Encapsulation 및 Data hide가 제공하는 보안을 우회하는 능력으로 본능적으로 싫어했습니다. 인터넷에서 몇 가지 기사를 읽었으며 일부 사람들은 합법적 인 용도로 좋은 아이디어라고 생각했습니다.

O ++ 전문가가 C ++의 친구 기능에 대해 무엇을 말합니까? 그냥 넘어 가야합니까, 아니면 그것에 대해 더 배워야합니까?


@all : 굉장한 답변과 의견, 이것은 배울 수있는 좋은 방법입니다. 교과서에서 그런 세부 사항으로 친구에 대해 배울 수있는 방법이 없습니다.
nikhil

답변:


13

해당 클래스의 C ++ 클래스 멤버와 관련된 모든 함수를 작성하는 것이 항상 편리한 것은 아닙니다. 예를 들어, 스칼라 곱셈을 사용한 벡터 대수의 구현을 상상해보십시오. 우리는 쓰고 싶다 :

 double a;
 Vector v, w;
 w = v * a;

멤버 함수로이를 수행 할 수 있습니다.

public class Vector {
 ...
 Vector operator*(double a);
}

그러나 우리는 또한 다음과 같이 쓰고 싶습니다 :

w = a * v

무료 기능이 필요합니다.

 Vector operator*(double a, Vector v)

friend키워드는이 사용을 지원하기 위해 C ++에 추가되었습니다. free 함수는 Vector 클래스 구현의 일부이며 동일한 헤더에서 선언되고 동일한 소스 파일에서 구현되어야합니다.

마찬가지로 friend컬렉션과 반복자와 같이 밀접하게 연결된 클래스의 구현을 단순화하는 데 사용할 수 있습니다 . 다시 말하지만, 두 클래스를 모두 같은 헤더로 선언하고 동일한 소스 파일로 구현합니다.


3
"무료 기능이 필요합니다." 아니요, 그렇지 않습니다 : inline Vector operator*(double a, Vector v) { return v*a; }. 사실 정식 솔루션.
MSalters

1
@MSalters : 좋은 지적입니다. 나는 나쁜 예를 골랐다. 인라인 함수는 정의에 의한 자유 함수라고 생각하지만 친구 선언은 필요하지 않습니다.
kevin cline

4
@MSalters : *가 a와 v (x)를 정식으로 존중하는 경우에만 유효합니다. 벡터 컴포넌트가 일반적인 경우 (스칼라 일 필요는 없음) 피연산자 순서를 유지해야합니다.
Emilio Garavaglia

꽤 이론적입니다. 아마도 일반적이지 않은 일반적인 경우는 inline Vector operator*(double a, Vector v) { return -v*a; }우정이 필요하지 않을 것입니다.
MSalters

16

친구 기능은 캡슐화 측면에서 멤버 기능과 다르지 않습니다. 그러나 특히 템플릿과 관련하여보다 일반적인 경우와 같은 다른 이점을 제공 할 수 있습니다. 또한 일부 연산자는 자유 기능으로 만 지정할 수 있으므로 멤버 액세스 권한을 가지려면을 수행해야합니다 friend.

그것은하는 것이 좋습니다 friend당신은 공개하고 싶지 않은 일을하도록 강요보다는 하나의 함수. 그것은 전 세계가 단 하나의 기능 대신 그것을 사용할 수 있음을 의미합니다.


친구 기능의 경우 +1 은 캡슐화 측면에서 멤버 기능과 다르지 않습니다. 이것은 공용 멤버 기능에만 해당됩니다.
TheFogger

1
@TheFogger : 논란의 여지없이, friend단일 TU에서만 선언 된 것과 같이 "비공개"인 함수 도 가능 합니다.
DeadMG

5

자신이하는 일에 열정이 있다면 C ++에 관한 모든 것을 배우게 될 것이다. 그들이 무엇을 사용하는지, 어떻게 사용하는지 배우고 나서 사용하지 않기로 결정하십시오. 최소한 C ++의이 패싯을 사용하는 다른 사람의 코드를 읽을 때 준비해야합니다.


5

" OOPs 전문가의 말은 ... "주로 C ++의 전문가가 자신의 사양에 따라 순수 주의자 언어가 아니고 싶지 않다는 점에 달려 있습니다.

OOP Zealots는 C ++ (Smalltalk 및 Java와 같은)을 사용하지 않습니다.

함수형 프로그래밍 zelot은 C ++을 사용하지 않습니다 (LISP 및 그 후속 버전을 선호 함)

대부분의 OOP 전문가는 C ++의 OOP 부분이 스몰 토크처럼 동작하기를 원하기 때문에 친구 기능을 싫어합니다. 그러나 C ++은 스몰 토크가 아니며, 클래스가 원하는 함수가 클래스의 친구가 될 수없는 간단한 이유 때문에 친구가 캡슐화를 깨뜨리지 않는다는 것을 이해할 수도 없습니다 .

사이 그리고 "기능"에서, 점 스탠드 a.fn(b)fn(a,b)차이 (여기서 없다 fn침범 당사자가 동일은 : 친구입니다). 단순히 하나의 구문이 다른 것보다 더 적합 할 수있다 : FN이에 대한 교환 법칙이 성립하는 경우 ab, fn(a,b)다음 아마도 더 적합합니다 a.fn(b). (여기서 "특별한 역할"즉, 사실, 그렇지 않은를 갖는 모습)


1
Java를 좋아하는“OOP zealots”는 OOP를 이해하지 못했습니다. 게터? 세터? 클로저에 대한 간단한 구문이 없습니까? Alan Kay의 말을 인용하자면, 이것은 그가 OOP를 상상 한 방식이 아닙니다.
Konrad Rudolph

@ Konrad : zealots는 매우 무제한 세트입니다. 주어진 zealot보다 zealot이 더 많은 zealot이 항상 있습니다.
Emilio Garavaglia

마지막 단락이 정말 마음에 들었 기 때문에 투표를했습니다. 많은 의미가 있습니다.
julealgon

5

"친구"가 캡슐화를 위반합니까?

아니 그렇지 않아. "친구"는 회원 자격과 마찬가지로 액세스 권한을 부여하기위한 명시 적 메커니즘입니다. 표준 준수 프로그램에서는 소스를 수정하지 않고 클래스에 대한 액세스 권한을 부여 할 수 없습니다.


2

C ++ FAQ는 간결입니다 :

할 수 있으면 회원을, 필요에 따라 친구를 사용하십시오.

FAQ는 우정에 대해 더 유용한 사고 방식 중 하나를 제시합니다.

많은 사람들이 친구 기능을 수업 외의 것으로 생각합니다. 대신, 친구 기능을 클래스의 공용 인터페이스의 일부로 생각하십시오. 클래스 선언의 친구 함수는 캡슐화를 위반하는 것 이상으로 캡슐화를 위반하지 않습니다. 둘 다 클래스의 비공개 부분에 액세스하는 것과 관련하여 정확히 동일한 권한을 갖습니다.

아마도 가장 친한 친구 기능은 I / O에 <<를 오버로드하는 것입니다.


0

프렌드 함수는 사용자 정의 연산자 정의에 가장 적합합니다. 다른 상황에서는 유용하지만 친구 클래스를 자주 지정하면 디자인 우회를 할 수 있습니다 (코드를 작성하는 동안 사용하기에 좋은 자체 점검).

원래 질문의 "보안"진술에주의하십시오. 액세스 수정자는 컴파일러와 마찬가지로 실수로 잘못된 코드를 작성하지 못하도록 방지합니다. 액세스 수정자는 인터페이스를 제한하고 클래스를 사용하는 데 중요한 기능 (공개 및 보호)과 유지 관리자 (개인)를 위해 클래스를 더 예쁘게 만드는 데 사용 된 기능을 전달합니다. 수정자는 개인 데이터를 얻는 많은 방법이 있다는 점에서 보안을 구성하지 않습니다. 예를 들어, 수업과 규모에 대한 포인터를 얻고 낚시를하십시오.


-2

C ++ 프렌드 함수는 다음 기능과 밀접한 관련이 있습니다.

  1. 무료 기능
  2. 정적 함수
  3. 친구 기능

즉,이 포인터가 없으므로 클래스 / 객체 외부에 있습니다. 반면에, 그들은 종종 다시 클래스에 속하는 매개 변수를 사용합니다. 다음은 링크를 명확하게하는 예입니다.

class B;
class A {
public:
    friend void f(A &a, B &b);
private:
    int m_a;
};
class B {
public:
   friend void f(A &a, B &b);
private:
   int m_b;
};
void f(A &a, B &b) { /* uses both A's and B's private data */ }

정적 함수와 friend 함수의 유일한 차이점은 friend 함수가 여러 클래스를 사용할 수 있다는 것입니다.

C ++에서 프렌드 메커니즘을 사용하려면 약 10-15 년의 C ++ 프로그래밍 방법에 대한 경험이있는 프로그래머가 필요하므로 처음에는 피해야합니다. 고급 기능입니다.


7
그리고 당신은 어떻게 10-15 년을 파생 시켰습니까?
DeadMG

10-15 년은 실제로 실제로 필요한 시점부터 시작됩니다.
tp1

3
그래서 당신은 임의로 숫자를 구성했습니다.
DeadMG

3
-1 : "피해야합니다." C ++의 모든 기능은 문제를 해결하기 위해 만들어졌습니다. 문제가 발생하면 적절한 기능을 사용하십시오.
kevin cline

-1 주셔서 감사합니다. 그 의견에 대한 이유가있었습니다. 모든 기능이 초보자에게 적합하지는 않다는 것이 어려운 개념이라고 생각합니다.
tp1
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.