2017-03-29 3 views
6

이전에 C++에서 연산자의 오버로드에 대해 클래스의 friend 함수뿐만 아니라 멤버 함수로 배웠습니다. 하지만 두 기술을 모두 사용하여 C++에서 연산자를 오버로드하는 방법을 알고 있습니다. 그러나 나는 아직도 혼란 스럽다 ** 어느 것이 더 낫다 **? 연산자를 오버로드하는 멤버 함수 또는 friend 함수? 사용해야하는 이유는 무엇입니까? 나를 안내하십시오! 귀하의 답변은 크게 감사하겠습니다. 나는 당신의 대답에 대해 기뻐하고 감사 할 것입니다.친구 대 연산자 오버로드 C++의 멤버 함수

+2

글로벌 비 친구 기능은 어떻습니까? 음, 어느 쪽이든, 항상 회원보다 글로벌하게가는 것을 선호합니다. – DeiDei

+0

친구가 아닌 세계적인 기능? 오버로드 된 연산자는 친구 또는 멤버 함수 일 수 있다고 생각했습니다. 하지만 고마워! 나는 그것도 검색 할 것이다. –

+0

'friend'는 클래스의'private' 멤버와'protected' 멤버에 대한 액세스 권한을 부여하기 위해서만 필요합니다. 그렇지 않은 경우에는 '친구'도 필요하지 않습니다. – DeiDei

답변

0

아마 이것에 대한 고정 된 규칙이 없기 때문에 가능한 한 회원 기능을 사용하여 연산자 오버로딩을 사용합니다. 이것의 주된 이유는 연산자를 클래스의 필수적인 부분으로 간주하고 클래스의 논리가보다 현지화되어 있다는 것입니다.

연산자 오버로드의 자유 함수를 선호하는 이유는 클래스를 가능한 한 가늘게 유지하는 것입니다 (필요한 경우에만 친구 만 사용).

운영자는 회원이 될 수 없으므로이 경우 토론이 없습니다. 주로 멤버 함수는 클래스 인스턴스를 항상 사용할 수있는 첫 번째 매개 변수로 사용합니다 (예 : i/o 용 연산자 < <).

2

회원 기능과 친구는 두 가지가 아니며 그 중 하나만 선택할 필요가 있습니다. 예를 들어 코드를 구현하고 코드를 호출하여 코드를 복제하는 것을 피하기 위해 둘 다 사용할 수 있습니다.

struct A 
{ 
    A operator+=(A const & second); 
}; 

A operator+(A const &first, A const &second) 
{ 
    A temp(first); 
    temp += second; 
    return temp; 
} 

그러나

당신이 선택하려는 경우 경우 는 회원 여부를해야 할 경우 기능, 여기에 내가 따라 규칙 하나 : 비 멤버 함수를 구현하기 ( friend 여부를) 나는 우리가 기대하는 대칭성을 존중하기 위해 이진 연산자을가집니다. 예 : A으로 int을 암시 적으로 (생성자가 int 인 생성자로) A으로 변환 할 수있는 가능성이 있습니다. 멤버 함수가 있으면 결과가 무엇입니까?

A a1, a2; 
a1 + a2; // OK 
a1 + 42; // OK 
42 + a2; // KO 

무료 기능을 사용하면 결과가 나타납니다.

A a1, a2; 
a1 + a2; // Ok 
a1 + 42; // Ok 
42 + a2; // Ok 

이 가능성을 사용하는 구체적인 C++ 클래스는 std::string입니다.

#include <iostream> 
#include <string> 

int main() 
{ 
    std::string s {"World"}; 
    // Works with absolutely no problem. 
    std::string chaine = "Hello " + s; 
    std::cout << chaine << std::endl; 
} 

여기에 당신을 도울 SO에 good link이다, 결론을합니다.

+0

고마워요 선생님 :-) 그것은 많은 도움이되었습니다 :-) –

3

선택은 "회원 또는 친구"가 아니라 "회원 또는 비회원"입니다.
(우정은 자주 남용되고 학교에서 너무 일찍 배웁니다.)

자유 함수가 호출 할 수있는 공용 멤버 함수를 항상 추가 할 수 있기 때문입니다. 예를 들어

:

class A 
{ 
public: 
    explicit A(int y) : x(y) {} 
    A plus(const A& y) const { return A{x + y.x}; } 
private: 
    int x; 
}; 

A operator+(const A& lhs, const A& rhs) { return lhs.plus(rhs); } 

선택하는 방법에 관해서 : 연산자는 왼쪽 피연산자와 같은 클래스의 인스턴스를하지 않을 경우, 그것은 그렇지 않으면이다, 무료로 기능해야 개인적인 취향 (또는 혼자가 아닌 경우 코딩 표준)의 문제.

예 :

: 해당 돌연변이 운영자가 운영자 (같은 ++=)은 멤버와 비 멤버와 다른 같이 돌연변이 연산자를 수행하는 것이 일반적 들어

// Can't be a member because the int is on the left. 
A operator+ (int x, const A& a) { return A{x} + a; } 

class B 
{ 
public: 
    explicit B(int y) : x(y) {} 
    B& operator+= (const B& y) { x += y.x; return *this; } 
private: 
    int x; 
}; 

B operator+(B lhs, const B& rhs) { return lhs += rhs; } 

하지만 당신은 물론, 너무이 밖으로 철자 할 수 있습니다

class C 
{ 
public: 
    explicit C(int y) : x(y) {} 
    C& add(const C& y) { x += y.x; return *this; } 
private: 
    int x; 
}; 

C& operator+=(C& lhs, const C& rhs) { return lhs.add(rhs); } 
C operator+(C lhs, const C& rhs) { return lhs += rhs; } 
+0

고마워 많은 :-) 좋은 정보 선생님! –

1

맛의 문제가 아니지만 일부 유스 케이스에는 분명히 두 가지 방법 중 하나가 필요합니다.

연산자가 디자인 할 클래스의 멤버 만 인수로 사용하면 캡슐화는 멤버 함수를 사용하여 투표합니다. 예 : 두 개체의 추가 : 당신이 작성하는 클래스의 회원이 연산자의 2 번째의 인수 반대에

class A { 
    ... 
    A operator + (const class A& other); // naturally a member function 
    ... 
}; 

, 만에 친구 기능

std::outstream& operator << (std::outstream& out, const class A& a); 

class A { 
    ... 
    friend std::outstream& operator << (std::outstream& out, const class A& a); // must be friend here 
}; 

을 사용할 수 있습니다 대부분 std::outstream 일 수 있지만 클래스가 표준 C++ 라이브러리에서 만들어 졌을 때 A 클래스가 존재하지 않았습니다 ...

+0

감사합니다 선생님 :-) 나는 당신에게서 새로운 것을 배웠습니다 :-) –