Turbo-C
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
터보-C 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
Lua 게시판
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
볼랜드포럼 광고 모집

C/C++ Q/A
[952] Re:friend 함수는 클래스의 캡슐화에 위배되는 것이 아닙니다.
오전&오후 [kkhhyy11] 1993 읽음    2002-08-05 12:12
프랜드함수를 이용하면 좋으점이 많지요..^^
특히 프랜드함수는 연산자오버로딩에 많이 쓰이지요..
멤버함수로 표현못하는것들을 friend함수로 하시면
간단 명료하게 만드실수 있으니까요..(특히 연사자에 관해서..)

제가 말씀드린건..
프랜드함수로 만드시면 더이상 클래스의 멤버함수가 아니라는거죠..
그런데..클래스의 데이타멤버에 아무런 제약없이 엑세스가 가능하게 됩니다..
이점이 바로 클래스의 추상화에 위배된다는거죠..^^
원래의 클래스 설계에서는 클래스의 데이타멤버는 멤버함수(인터페이스)를
통해서만 엑세스가 가능해야 합니다..
그런데 일반함수에서도 가능하게 되는거지요..friend라는 키워드를 사용하면
그러기때문에..
꼭 필요한 경우에만 사용하라는거지요..
클래스의 모든 멤버함수를 friend함수로 만들수는 없는거잖아요..^^
뭐 어떻게 구현하느냐는 프로그래머의 마음이겠지만요..^^


김백일 님이 쓰신 글 :
: 프렌드 함수는 보통 연산자 겹지정(operator overloading)을 위해 사용됩니다.
:
: 다음과 같은 2차원 벡터를 나타내는
: Vector(std::vector가 아닙니다.)라는 클래스를 정의해보죠.
: (다음은 'C++ 기초 플러스'(성안당)에 있는 내용을 정리한 겁니다.)
: 멤버 함수로
: 두 벡터의 덧셈, 뺄셈인 +과 - 연산과
: 상수를 곱하는 * 연산을 정의한다면 다음과 같습니다.
:
: class Vector
: {
: private:
:   double x, y;
: public:
:   Vector(double _x, double _y) : x(_x), y(_y) {};
:   Vector(const Vector& v) { x = v.x; y = v.y; }
:   double GetX() { return x; }
:   double GetY() { return y; }
:   void SetX(double _x) { x = _x; }
:   void SetY(double _y) { y = _y; }
:   Vector operator+(const Vector& b) { return Vector(x + b.x, y + b.y); }
:   Vector operator-(const Vector& b) { return Vector(x - b.x, y - b.y); }
:   Vector operator*(double n) { return Vector(n * x, n * y); }
: }
:
: 사용할 때는
:
: Vector a(1.0, 2.0), b(3.0, 4.0),
:   sum = a + b, diff = a - b;
:
: 라고 하면, 컴파일러가 다음과 같이 바꿉니다.
:
: sum = a.operator+(b), diff = a.operator-(b);
:
: 물론, sum은 (4.0, 6.0)은 diff는 (-2.0, -2.0)가 됩니다.
:
: operator*()를 테스트하려면
:
: Vector mul = a * 2.0;
:
: 이라고 쓰면,
: mul = a.operator*(2.0);
: 가 되어 mul이 (2.0, 4,0)이 되는데요,
: 만약 다음과 같이
:
: Vector mul = 2.0 * a;
:
: 라고 쓰면, 어떻게 될까요?
: 컴파일러가 다음과 같이 변형하게 되는데,
:
: mul = 2.0.operator*(a);
:
: 물론, 컴파일 에러가 나게 됩니다.
:
: 이런 문제를 해결하려면,
: operator*()를 멤버 함수가 아니라 다음과 같이 프렌드 일반 함수로 정의하면 됩니다.
:
: class Vector {
: private:
:   ...
: public:
:   ...
:   friend Vector operator*(const Vector& a, double n);
:   friend Vector operator*(double n, const Vector& a);
: }
:
: // 이렇게 짧은 함수는 inline을 붙이면 성능 향상에 도움이 됩니다.
: inline Vector operator*(const Vector& a, double n)
: {
:   return Vector(a.x * n, a.y * n);
: }
:
: inline Vector operator*(double n, const Vector& a)
: {
:   return Vector(n * a.x, n * a.y);
: }
:
:
: 그러면
:
: Vector mul = 2.0 * a;
:
: 가
:
: Vector mul = operator*(2.0, a)
:
: 로 바뀌므로 문제 없이 컴파일됩니다.
:
: 이번에는 다른 문제를 생각해보죠.
:
: 연산자 겹지정을 할 때는, 멤버 함수 대신 프렌드 일반 함수를 쓰실 것을 권합니다.
: operator+()와 operator-()의 경우도,
:
: class Vector {
:   ...
:   friend Vector operator+(const Vector& a, const Vector& b)
:   friend Vector operator-(const Vector& a, const Vector& b)
:   ...
: }
:
: inline Vector operator+(const Vector& a, const Vector& b)
: {
:   return Vector(a.x + b.x, a.y + b.y);
: }
:
: inline Vector operator-(const Vector& a, const Vector& b)
: {
:   return Vector(a.x - b.x, a.y - b.y);
: }
:
: 라고 쓰면, 대칭적인 코드가 되기 때문에 가독성이 더 좋습니다.
:
:
: 또다른 예를 들어보죠.
:
: Vector를 출력하려면 어떻게 해야 할까요?
:
: 예를 들어 다음과 같이 멤버함수로 정의해보죠.
:
: class Vector
: {
:   ...
:   void operator<<(ostream& os, const Vector& v);
:   ...
: };
:
: inline void Vector::operator<<(ostream& os, const Vector& v)
: {
:   os << "(" << x << "," << y << ")";
: }
:
:
: 라고 한다면,
:
: Vector v;
:
: 일때
:
: cout << v;
:
: 라고 쓸 수는 없습니다.
:
: cout.operator<<(v);
:
: 로 변형하면
:
: cout::operator<<(const Vector& v)
:
: 가 호출되어야 하는데, 이런 함수는 정의되어 있지 않기 때문이죠.
:
: 그러므로, 대신
:
: v << cout;
:
: 이라고 쓸 수 밖에는 없습니다. 상당히 어색하지요. -_-;
:
: 그래서 다음과 같이 프렌드 일반 함수로 정의합니다.
:
: class Vector
: {
:   ...
:   friend ostream& operator<<(ostream& os, const Vector& v);
:   ...
: };
:
: inline ostream& operator<<(ostream& os, const Vector& v)
: {
:   os << "(" << x << "," << y << ")";
:   return os;
: }
:
: 여기서 return 값을 ostream& 으로 한 것은 다음과 같이 연속해서 출력하는 경우를 위해서 입니다.
:
: cout << v << "is vector." << endl;
:
: ostream& 리턴값이 없다면,
:
: cout << v;
:
: 라고 쓸 수 밖에는 없죠.
:
: 하여튼 여기서는
:
: operator<<(cout, v)
:
: 가 호출되므로 문제없이 컴파일 됩니다.
:
: :
: : 주의사항 : friend 함수는 클래스의 추상화에 위배가 되기때문에
: : 많이 사용하면 안좋다고 그러네요..^^;
: : 그러니까 꼭 필요할때만 사용하시면 됩니다..
:
: 이것은 추상화라기보다는 캡슐화라는 겁니다.
:
: friend 함수는 클래스의 캡슐화에 위배되는 것이 아닙니다.
: 단지 멤버 함수를 다른 표현으로 바꾼 것에 불과합니다.
: 클래스 내부에서 (friend라는 키워드를 붙여서) 선언을 하지 않으면
: 쓸 수 없는 것은 멤버 함수와 마찬가지입니다.
:
: 다시 한 번 강조하지만, 연산자 겹지정을 할 때는 멤버 함수대신 프렌드 일반 함수를 사용하세요.
: 코드의 가독성도 높아지고, 코딩 에러도 줄일 수 있는 좋은 방법입니다.

:

+ -

관련 글 리스트
935 friend 이해가 잘안갑니다. 김경래 1704 2002/08/01
940     Re:friend 이해가 잘안갑니다. 오전&오후 1717 2002/08/02
945         friend 함수는 클래스의 캡슐화에 위배되는 것이 아닙니다. 김백일 1698 2002/08/03
952             Re:friend 함수는 클래스의 캡슐화에 위배되는 것이 아닙니다. 오전&오후 1993 2002/08/05
953                 [펌]friend는 OOP에 충실하지 않을 것일까? 김백일 1784 2002/08/05
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.