[C++] 함수 포인터와 함수 객체

Taeil Nam·2022년 11월 21일
0

C++

목록 보기
11/13
post-thumbnail

함수 포인터

함수 포인터

  • 함수의 메모리 주소를 값으로 가지는 포인터 변수.
  • 함수 포인터를 사용하면, 함수를 변수처럼 사용할 수 있음.
  • 함수의 메모리는 "CODE" 메모리 영역에 저장되어 있으며, 함수 포인터를 따라가면 "CODE" 메모리 영역에 있는 해당 함수의 내용이 들어있음.
  • 문법 : 함수 반환 자료형(함수 포인터 이름)(함수 매개 변수 자료형, ...) = 함수 이름
    Ex) int(
    fp)(int, int) = Print;

멤버 함수 포인터

  • 기존 함수 포인터는 전역 함수 및 정적 함수만 사용 가능.
  • 멤버 함수 포인터는 전역 함수 및 정적 함수와 함수 호출 규약이 다르기 때문에 문법이 다름.
  • 문법 : 함수 반환 자료형(클래스::*멤버 함수 포인터 이름)(함수 매개 변수 자료형, ...) = &멤버 함수 이름
  • '&' 기호를 꼭 붙여줘야 되는 것에 주의.
    Ex) int(Player::*mfp)(int, int) = &Player::PrintID;

함수 호출 규약

1. __cdecl

  • 전역 함수, 정적 함수의 함수 호출 규약.
  • 스택 메모리 정리 주체 = 함수 호출자. (main() 에서 printf() 호출시 main()이 함수 호출자)
  • 호출자가 피호출자 함수의 매개 변수 정보를 알고 있기 때문에, 가변 인자 사용 가능.

2. __thiscall

  • 멤버 함수의 함수 호출 규약.
  • 가변 인자를 사용하지 않는 멤버 함수에서 사용.
  • 자신이 속한 객체를 가리키는 this 포인터를 추가로 가지고 있음. (숨겨져 있음)

구현

#include <iostream>
using namespace std;

int Add(int a, int b)
{
    cout << "Add() 호출" << endl;
    return a + b;
}

class Player
{
public:
    Player(int pid) : _pid(pid) { }
    void PrintID()
    {
        cout << "PrintID() 호출 : " << _pid << endl;
    }

public:
    int _pid;
};

int main()
{
    // 함수 포인터 fp에 Add() 메모리 주소 저장.
    int(*fp)(int, int) = Add;

    fp(1, 2); // 함수 포인터로 Add(1, 2) 호출.
    
    // 멤버 함수 포인터 mfp에 PrintID() 메모리 주소 저장.
    void(Player::*mfp)() = &Player::PrintID;

    Player* p = new Player(1); // Player 객체 p 생성.
    (p->*mfp)(); // 멤버 함수 포인터로 Player::PrintID(1) 호출.
    delete p;
}

함수 객체 (Functor)

  • 함수처럼 동작하는 객체.
  • '()' 연산자 오버로딩 필요.
  • 추후 서버쪽에서 커맨드 패턴으로 활용.
#include <iostream>
using namespace std;

class Functor
{
public:
    void operator()() // () 연산자 오버로딩
    {
        cout << "Functor Test" << endl;
        cout << "Value = " << _value << endl;
    }

    void operator()(int n) // () 연산자 오버로딩 + 매개 변수 추가
    {
        cout << "Functor Test" << endl;
        cout << "Value = " << n << endl;
    }

public:
    int _value = 0;
};

int main()
{
    Functor functor; // 함수 객체 생성.

    functor();  // operator() 호출.
    functor(314); // operator(314) 호출.
}

0개의 댓글