13.10 Overloading the parenthesis operator

주홍영·2022년 3월 18일
0

Learncpp.com

목록 보기
153/199

https://www.learncpp.com/cpp-tutorial/overloading-the-parenthesis-operator/

이제껏 본 overloaded된 operator는 parameter는 결정할 수 있었지만 parameter의 갯수를
정하지는 않았다. 예를 들어 operator==의 경우에는 언제나 두개의 parameter만을 다룬다
!operator의 경우에는 하나의 parameter만을 다룬다

Parenthesis operator( () )의 경우에는 우리가 타입과 갯수 모두 정할 수 있다

두가지 항상 염두에 두어야할 사실이 있다
첫째, parenthesis operator는 항상 member function으로 구현되어야 한다
둘째, non-object-oriented c++에서는 ()operator는 함수를 호출하는데 사용하곤 했다
클래스의 경우에는 단지 operator()라는 함수를 호출하는데 사용될 뿐이다

An example

다음의 example을 살펴보자

class Matrix
{
private:
    double data[4][4]{};
};

data의 경우 4x4인 행렬이다
subscript operator의 경우 1차원 배열이였는데 이번의 경우에는 2차원 배열이기에 기존의 subscript operator로는 충분치 않다

그러나 () operator의 경우 우리가 원하는 만큼 parameter를 받을 수 있다
따라서 다음과 같은 방법으로 2차원 행렬에 접근한다

#include <cassert> // for assert()

class Matrix
{
private:
    double m_data[4][4]{};

public:
    double& operator()(int row, int col);
    double operator()(int row, int col) const; // for const objects
};

double& Matrix::operator()(int row, int col)
{
    assert(col >= 0 && col < 4);
    assert(row >= 0 && row < 4);

    return m_data[row][col];
}

double Matrix::operator()(int row, int col) const
{
    assert(col >= 0 && col < 4);
    assert(row >= 0 && row < 4);

    return m_data[row][col];
}

위와 같이 operator()를 두개의 int parameter를 받도록 정의했다
이제 다음과 같이 실제로 사용하면 된다

#include <iostream>

int main()
{
    Matrix matrix;
    matrix(1, 2) = 4.5;
    std::cout << matrix(1, 2) << '\n';

    return 0;
}

parameter를 아예 받지 않고도 사용가능하다

#include <iostream>

int main()
{
    Matrix matrix{};
    matrix(1, 2) = 4.5;
    matrix(); // erase matrix
    std::cout << matrix(1, 2) << '\n';

    return 0;
}

Having fun with functors

Operator()는 흔히 functor를 구현하는데 많이 사용된다
클래스를 function 처럼 사용하는 것이다
normal function에 비해서 functor의 장점은 class 기반이라 member variable에
데이터를 저장할 수 있다는 것이다

여기 간단한 functor의 예시이다

#include <iostream>

class Accumulator
{
private:
    int m_counter{ 0 };

public:
    int operator() (int i) { return (m_counter += i); }
};

int main()
{
    Accumulator acc{};
    std::cout << acc(10) << '\n'; // prints 10
    std::cout << acc(20) << '\n'; // prints 30

    return 0;
}

위의 코드를 보면 acc라는 object를 함수처럼 사용하고 있는 것을 알 수 있다
하지만 acc object의 member variable에 값을 저장해서 사용하고 있다는 것을 알 수 있다

이를 보고 왜 normal function에 static variable로도 할 수 있는 것 아닌가 라고 생각할 수도 있다. 하지만 function의 경우 오직 globaly하게 하나의 instance 밖에 가질 수 없다
따라서 우리는 한번에 하나의 static variable 만 사용하도록 제약을 받는다
하지만 functor를 사용하면 우리는 원하는 만큼 instance를 만들어서 각각 분리된 상황에서 object와 member variable을 사용할 수 있다

profile
청룡동거주민

0개의 댓글