[c++] 연산자 오버로딩 : 멤버 함수 대 비 멤버 함수?

멤버 함수로 선언 된 오버로드 된 연산자는 하나의 매개 변수 만 가질 수 있고 자동으로 전달되는 다른 매개 변수는 포인터 이기 때문에 비대칭 이라는 것을 읽었습니다 this. 따라서 이들을 비교할 기준이 없습니다. 반면 a friend로 선언 된 오버로드 된 연산자는 동일한 유형의 두 인수를 전달하므로 비교할 수 있기 때문에 대칭 입니다.

내 질문은 포인터의 lvalue를 참조와 비교할 수 있는데 왜 친구가 선호됩니까? (비대칭 버전을 사용하면 대칭과 동일한 결과가 나타납니다.) STL 알고리즘이 대칭 버전 만 사용하는 이유는 무엇입니까?



답변

연산자 오버로드 된 함수를 멤버 함수로 정의하면 컴파일러는 식 s1 + s2s1.operator+(s2). 즉, 연산자 오버로드 된 멤버 함수가 첫 번째 피연산자에서 호출됩니다. 이것이 멤버 함수가 작동하는 방식입니다!

그러나 첫 번째 피연산자가 클래스가 아니면 어떻게 될까요? 첫 번째 피연산자가 클래스 유형이 아닌 연산자를 오버로드하려는 경우 큰 문제가 double있습니다. 그래서 당신은 이렇게 쓸 수 없습니다 10.0 + s2. 그러나 같은 식에 대해 연산자 오버로드 멤버 함수를 작성할 수 있습니다 s1 + 10.0.

순서 문제 를 해결하기 위해 멤버 friend에 액세스해야하는 경우 연산자 오버로드 함수를 정의 private합니다. 비공개 회원에 액세스해야 friend때만 만드십시오 . 그렇지 않으면 단순히 캡슐화 를 향상시키기 위해 친구가 아닌 비회원 함수로 만드십시오 !

class Sample
{
 public:
    Sample operator + (const Sample& op2); //works with s1 + s2
    Sample operator + (double op2); //works with s1 + 10.0

   //Make it `friend` only when it needs to access private members. 
   //Otherwise simply make it **non-friend non-member** function.
    friend Sample operator + (double op1, const Sample& op2); //works with 10.0 + s2
}

읽어보기 :
피연산자 순서의 약간의 문제
비 멤버 함수가 캡슐화를 개선하는 방법


답변

전역 연산자 오버로드와 멤버 함수 연산자 오버로드 friend사이이기 때문에 연산자 오버로드와 멤버 함수 연산자 오버로드를 반드시 구분할 필요는 없습니다 .

전역 연산자 오버로드 를 선호하는 한 가지 이유 는 이항 연산자 의 오른쪽 에 클래스 유형이 나타나는 식을 허용하려는 경우 입니다. 예를 들면 :

Foo f = 100;
int x = 10;
cout << x + f;

이것은 전역 연산자 오버로드가있는 경우에만 작동합니다.

Foo 연산자 + (int x, const Foo & f);

전역 연산자 오버로드가 반드시 friend함수일 필요는 없습니다 . 의 비공개 멤버에 대한 액세스가 필요한 경우에만 필요 Foo하지만 항상 그런 것은 아닙니다.

관계없이 Foo다음과 같이 멤버 함수 연산자 오버로드 만있는 경우 :

class Foo
{
  ...
  Foo operator + (int x);
  ...
};

… 그러면 더하기 연산자 Foo왼쪽 에 인스턴스가 나타나는 표현식 만 가질 수 있습니다 .


답변