객체지향프로그래밍(27) - friend 키워드란?

friend 키워드 이해

Featured image

🔚 짧게 하는 복습

✅ 1. = 연산자와 복사 생성자의 차이를 안다.

✅ 2. 복사 생성자의 쓰임을 안다.

✅ 3. = 연산자와 복사 생성자의 오버로딩 시 주의사항을 안다.

✅ 4. 오버로딩을 할 때 주의사항을 안다.

혹시 기억이 안 난다면, 다시 돌아가자


오늘은 객체지향 프로그래밍에서 다룰 마지막 기능 friend이다. (물론 마지막 강의는 아니다.)

바로 알아보자.


friend란?

friend란 친구라는 뜻으로, friend 키워드를 앞에 붙인 메소드나 정의된 클래스는 서로의 private 변수에 접근할 수 있게 해준다.

사용하는 방법은 우선 friend로 묶을 클래스의 헤더만 정의를 위에서 해준다. (필수)

그리고 friend 메소드로 묶을 클래스 안에서 모두 friend 메소드의 헤더를 정의한다.

마지막에 전역 범위에서 범위 지정자, friend 키워드 없이 함수를 정의한 후 사용하면 된다.

백문이 불여일견으로, 직접 코드를 보자.

보이다시피 양쪽의 private 변수에 get_ 함수 없이 접근할 수 있다.

또한, 아래와 같이, 클래스 붙여서도 사용할 수 있다.


friend 키워드의 문제점

간단히 다루고 지나갔지만 객체지향의 4대 요소 중, 캡슐화라는 것이 있었다.

캡슐화하나의 캡슐로 다루고, data hiding을 통해 노출하고 싶은 부분에만 접근을 허용한다는 성질이었다.

그런데 이 friend란 키워드는 벽을 허무는 역할을 한다.

외부에서 접근해서는 안 되는 영역을 접근시켜준다.

이는 객체지향의 본질을 위협하기 때문에, 만약 friend 메소드가 많이 사용되었다면 그 설계를 의심해볼 필요가 있다.

대부분 더 좋은 구조가 있을 가능성이 크다.


friend 키워드를 이용한 연산자 오버로딩

하지만 friend 키워드를 피하기엔, 너무 편리한 상황이 있다.

대표적인 상황은 연산자 오버로딩이다.

class counter{
private:
    int count;

public:
    counter() : count(0) {};
    counter(int _count) : counter(_count) {}

    counter operator + (const counter& c2){
        return counter(count + c2.count);
    }
};

int main(){
    counter a1 = counter(10);

    counter a2 = a1 + 10;

    counter a3 = 10 + a1;// 얘는 안됨
}

이 코드에서 두 번째가 안되는 이유가 무엇이라고 했는가?

연산자란 기본적으로 연산자의 왼쪽 객체에서 호출된다고 했기 때문이다.

이런 경우 friend 키워드를 이용한 연산자 오버로딩은 코드에 유연함을 더한다.

분명 operator +는 하나의 매개 변수를 받지만, friend로 오버로딩 operator +는 두 개의 매개 변수를 받는다.

또한, 어느 쪽을 리터럴 상수로 받더라도 묵시적 형변환을 만들어 낼 수 있다. (편리하지만 그만큼 위험한 행동이라고 했다.)


가독성을 위한 활용

counter 메소드의 값 제곱 반환하기 위한 메소드를 square라고 해보자.

원래는 아래와 같이 호출하는 것이 정상이다.

a1.square();

하지만, 이는 조금 모호한 느낌이 있다.

우선 a1 자체를 제곱하는 것으로 오해할 수 있고, 두 번째는 값을 반환하기만 한다면 객체의 기능이라고 보기엔 어렵다.

그래서 종합적으로는 우리가 배운 함수를 생각해보면 아래와 같은 것에 익숙할 것이다.

square(a1);

이럴 때에도, friend 함수를 이용할 수 있다.

#include <iostream>
using namespace std;

class counter{
private:
    int count;

public:
    counter() : count(0) {};
    counter(int _count) : count(_count) {}

    friend int square(const counter& c);
};

int square(const counter &c){
    return c.count*c.count;
}

int main(){
    counter a1 = counter(10);
    cout<< square(a1);
}


강의를 마치며

오늘로 객체 프로그래밍의 기술적인 내용은 모두 다루었다.

다음 강의부터는 약간의 OOP의 이론적인 내용을 복기해보겠다.


📖 오늘의 핵심(다 알기 전까지는 넘어가지 말자❗)

✅ 1. friend 키워드의 정의와 활용을 안다.

✅ 2. friend 키워드가 어떤 점에서 위험한 지 안다.

⚠️ friend 키워드를 남발하지 말자

💣 과제, 없음