Qaupot Blog
Software Engineering, Trip

208. friend

🕐 Thu, 06 Mar 2014 09:00:00 GMT 🕓 Tue, 31 Aug 2021 10:20:00 GMT

friend 키워드

friend 키워드는 지정된 해당 함수 혹은 클래스에 대해 자신의 private 나 protected 멤버를 public 권한으로 접근할 수 있도록 합니다.

클래스 전체에 대해 지정할 경우

friend class 클래스명;

전역 함수에 대해 지정할 경우

friend 함수원형;

클래스의 멤버 함수에 대해 지정할 경우

friend 클래스명::함수원형;

friend 키워드는 어디에 사용하는가?

friend 키워드는 객체의 사용을 편하게 만들지만, 객체의 캡슐화를 무너뜨립니다.

friend 를 남발하는건 좋은 습관이 아닙니다.
그러나, 때때로 코드 단위에서 사용 방법을 유도할때 유용하게 쓰이기도 합니다.

#include <iostream>

class SharedNumber
{
private:
    int* intPtr;
    SharedNumber(int num)
    {
        this->intPtr = new int;
        *this->intPtr = num;
    }
public:
    int getNumber()
    {
        return *intPtr;
    }
    void setNumber(int num)
    {
        *intPtr = num;
    }
    friend class SharedNumberFactory;
};

class SharedNumberFactory
{
public:
    static SharedNumber MakeSharedNumber(int num)
    {
        return SharedNumber(num);
    }
};

int main(int argc, char** argv)
{
    SharedNumber firstShared = SharedNumberFactory::MakeSharedNumber(5);
    SharedNumber secondShared = firstShared;

    printf("%d %d\n", firstShared.getNumber(), secondShared.getNumber());
    secondShared.setNumber(20);
    printf("%d %d\n", firstShared.getNumber(), secondShared.getNumber());

    return 0;
}
5 5
20 20

위의 코드는 사용 예제입니다.

SharedNumber 는 복사된 모든 인스턴스들이 같은 숫자를 가르키도록 디자인 되었습니다.

  • 생성자를 숨기고 SharedNumberFactory 에만 friend 로 접근을 허용합니다.
  • SharedNumberFactory 에서만 SharedNumber 의 최초 생성을 할 수 있습니다.

SharedNumber 는 int 형 포인터 하나를 가지고 있으며 최초 생성시 메모리를 할당합니다.
자연스럽게 복사된 다른 SharedNumber 는 같은 포인터를 가집니다.

즉, SharedNumberFactory 를 통해서만 SharedNumber 를 생성할 수 있도록 코드 상에서 제한을 한 것입니다.

  • 이 규칙을 지키지 않으면 컴파일 에러가 나기 때문에 런타임에 에러를 발견하는 것 보다 훨씬 안전합니다.
static SharedNumber MakeSharedNumber(int num)

별도의 상속 절차가 없는 경우에는 SharedNumber 내 상기 구현을 통해 Factory Class 대신 사용하기도 합니다.

friend 키워드를 사용할때의 선언 배치

class 에 대해 지정을 할 때에는 별다른 문제가 없지만, 전역 함수나 멤버 함수의 경우 반드시 friend 의 대상이 되는 선언이 앞서서 나와야 합니다. 만약 위의 예제를 멤버 함수에 대해 지정할 경우 아래와 같이 선언해야 합니다.

// SharedNumberFactory의 메소드 선언에 필요
class SharedNumber; 

class SharedNumberFactory
{
public:
    // SharedNumber의 friend 선언에 필요
    static SharedNumber MakeSharedNumber(int num); 
};

class SharedNumber
{
private:
    int* intPtr;
    SharedNumber(int num)
    {
        this->intPtr = new int;
        *this->intPtr = num;
    }
public:
    int getNumber()
    {
        return *intPtr;
    }
    void setNumber(int num)
    {
        *intPtr = num;
    }
    friend class SharedNumber SharedNumberFactory::MakeSharedNumber(int num);
};

SharedNumber SharedNumberFactory :: MakeSharedNumber(int num)
{
    return SharedNumber(num);
}
이 블로그는 개인 블로그입니다. 게시글은 오류를 포함하고 있을 수 있지만, 저자는 오류를 해결하기 위해 노력하고 있습니다.
게시글에 별도의 고지가 없는 경우, 크리에이티브 커먼즈 저작자표시-비영리-변경금지 4.0 라이선스를 따릅니다.

This blog is personal blog. published posts may contain some errors, but author doing efforts to clear errors.
If post have not notice of license, it under creative commons Attribution-NonCommercial-NoDerivatives 4.0.