드물게 사용되는 키워드 중 하나인 friend 키워드는 클래스의 멤버변수에 대한 접근 권한을 주는 키워드인데, 사실 캡슐화 측면에서 바람직하지 않게 보이기도 한다. friend키워드를 꼭 사용하지 않아도 getter함수나 setter 함수를 제공함으로써 충분히 멤버변수에 접근할 수 있다. 그래도 가끔은 friend 키워드를 사용할 때가 더 깔끔하고 가독성이 좋다.
friend 키워드의 사용방식
friend는 접근에 관한 키워드므로 상식적으로 주체가 되는 클래스가 외부 클래스나 외부 함수에 허용해주는 형태가 되어야 한다. friend로 지정된 클래스나 함수는 제한 없이 멤버변수에 접근할 수 있다.
Class간 사용 예>
extern 과 비슷하게 사용된다. 외부의 클래스가 자신의 멤버변수에 접근 가능하도록 하기 위해서 위와 같이 내부에서
friend class 클래스 이름;
을 선언하고 있다.
draw 클래스에서는 내부의 멤버함수 print()에서 point의 객체를 인수로 받아 직접 멤버에 접근을 시도한다. 매우 간편해 보이고 자주사용하고 싶어지겠지만, 위와 같은 경우는 번거롭더라도 getter, setter 함수를 작성하여 사용할 것을 권한다. 단순히 print함수에서만이 아니라 draw클래스의 모든 멤버함수가 Point 클래스의 멤버에 직접 접근가능하기 때문이다. 따라서 Point 클래스의 멤버에 대한 안정성은 보장되지 않는다.
전역 함수에 대한 사용 예>
적절한 전방 선언(1줄과 2줄)을 통해서 '선언되지 않은 식별자' 오류가 나지 않도록 한다. 클래스와 별반 다르지 않고, 이해하기도 쉽다. 또한 setter, getter 함수보다는 깔끔하게 함수를 작성할 수 있지만, 이런 편의성이 꼭 필요한 것은 아니다.
연산자 오버로딩에서의 사용 예>
간단한 복소수에 관한 클래스다. 기본적인 표현은 제대로 작동하는 것 같다. 아무튼 복소수의 연산에 관한 연산자의 오버로딩이 필요하다. 우선 덧셈에 관한 연산을 보자. 기본 생성자를 생성하고 +연산자를 오버로딩 하였다.
동작은 제대로 되지만, 복소수의 특성상 complex 타입이 아닌 int형 타입과도 연산이 가능해야 할 것이다. 그래서 다음과 같이 +연산자를 오버로딩 한다.
그럼
R = 3+C;
의 경우는?
2가지 피 연산자를 위한 전역함수
문제는 complex + int 형과 int + complex가 동일한 연산이라는 데 있다. 따라서 int + complex에 대한 +연산자가 오버로딩 되어야 하는데, 이 경우 int 타입 내부에 이런 연산에 대한 정의를 가지고 있어야 한다. 하지만 내장 타입에 대한 연산자를 오버로딩 할 방도가 있겠는가? 이런 경우 연산자 전역 함수를 이용한 연산자 오버로딩을 해야 한다. 보통 전역 함수로 연산자 오버로딩을 할 경우 가독성을 위해 friend키워드를 사용한다.
전역 함수로 operator+함수를 사용하여 int 타입 + complex타입의 경우에도 동일한 연산을 할 수 있다. 누군가는 캡슐화를 위해서 getter, setter 함수를 정의하여 한다고 할 수 있겠지만, 계산이 복잡해지면 매우 가독성이 떨어진다.
또한 +연산은 피 연산자를 const로 한정하기 때문에, 변조에 대한 위험도 없기 때문에, 이런 경우는 꽤 괜찮은 사용이라고 보여진다. 사실 위 함수가 연산을 할 필요는 없다. frined를 사용하지 않고, 단순히 return CX+ X; 라고 하면 된다. 이 경우는 교환법칙이 성립하므로 상관이 없지만, 교환법칙이 성립하지 않는 경우는 friend로 설정한 후 직접 연산에 대한 내용을 작성해야 한다.
참고로 멤버함수의 경우는 const를 함수 끝에 붙였는데 외부함수는 그렇지 않은지 이해가 안 간다면, const에 대한 공부가 필요하다. 간단히 말해 const를 함수 끝에 붙인 경우는 멤버 함수에 관한 문법이고, 객체를 변조하지 않는다는 의미다. 객체를 변조하지 않는다는 의미는 객체의 멤버변수의 값을 변경하지 않는 다는 의미인데, 여기서 외부 함수는 객체에 속한 함수가 아니기 때문에, const 한정자는 단순히 피 연산자와 리턴 값에만 붙여 놓았다. 피 연산자의 값이 왜 const인지 이해가 안 간다면 메모리 상에서 임시객체가 생성되는 것을 이해해야 하는데, 임시객체에 관한 공부를 하면 된다.