title: “C++ 13. 가상 함수(오버라이딩과 동적바인딩)” categories:

  • CspecialCharspecialChar

    #C++ 13. 가상 함수(오버라이딩과 동적바인딩) : 네이버 블로그

일단 오버라딩에 대해 설명하겠다

오버라이딩은 한국어로 재정의이다.

즉 어떠한 변수나 함수를 재정의하는 것이다

오버라이딩을 하기 위해서는 virtual이 필요하다

이는 가상 함수로 불리는데 어떠한 함수나 변수의 정의를 늦춤으로써 다르게 정의된 함수나 변수가 있는지 확인 후 없으면 기존의 함수나 변수를 출력, 있으면 바뀐 함수나 변수를 출력한다.

즉 일단 미루고서 재정의된 함수나 변수가 있는지 찾고 있으면 바꾼다

간단히 예시를 들겠다

#include
using namespace std;
class people {
public:
 virtual void f() {
 cout << "people::f()" << endl;
 }
};
class student:public people {
public:
 void f() {
 cout << "student::f()"<<endl;
 }
};
int main() {
 student A;
 A.f();
}

people과 student는 각각 자신의 맴버 f를 가지고 있다

이 f는 이름과 매개변수가 같으므로 같은 함수이다(내용은 다름)

둘중 어떤것을 사용할지 구별하기 위해 people의 f는 virtual이 되어 있다

main안에서는 student A가 선언된다

A는 만들어지면서 student는 people을 상속함으로써 people의 맴버를 가져온다

people의 맴버는 f()지만 virtual이 있으므로 실행이 될때까지 기다린다

people이 만들어지고 student가 생성된다. student는 f를 가지고 있다

f는 student에 있으므로 people의 f가 아닌 student의 f가 사용된다

이렇게 클래스에 따라 각기 다른 맴버를 사용할 수 있다

우리는 이제 동적 바인딩에 대해서도 알아야 한다

동적 바인딩이란 가상 함수가 있는 코드를 컴파일 할 때 가상 함수를 필요할 때 찾아 쓰는 과정이다

즉 함수가 정의되어 사용되지 않고 호출된다면 오버라디이딩 된 함수 중에서 찾아 실행된다

먼저 에제를 보자

#include
using namespace std;
class people {
public:
 virtual void f() {
 cout << "people::f()" << endl;
 }
};
class student:public people {
public:
 void f() {
 cout << "student::f()"<f();

 people \*C=B;
 C->f();
}

main 안에만 보겠다

student A는 student 와 people의 맴버를 모두 갖고 있다

A.f()를 실행하게 되면 people에 있는 맴버는 virtual이므로 재정의되어 student에 있는 f가 실행되게 된다

이후 student *B는 A의 주소를 가진다

B의 f를 실행하게 되면 B는 student의 f를 실행하게 된다

3번째로 people *C가 선언된다

이 C는 B를 받음으로써 기본 클래스인 people부분만 받게 된다

C의 f()를 실행하게 되면 people객체 포인터므로 people의 f가 실행 된다 생각할 수도 있지만

student의 f가 실행되게 된다

왜 이런 결과가 나오게 되는 것일까

동적 바인딩이 발생하는 경우에는 파생 클래스의 객체에 대해, 기본 클래스의 포인터로 가상 함수가 호출될 때 일어난다.

즉 상속이 있고 기본클래스의 포인터로 가상함수가 호출될 때 동적 바인딩이 일어난다

이에 주의하면서 오버라이딩을 사용해야 한다.

우리는 오버라이딩을 사용하면서 맴버를 재정의 하는 방법을 알았다

그럼 재정의된 맴버를 사용할 수 없을까?

바로 범위지정연산자 :: 을 사용하면 된다

범위지정연산자를 사용하는 방법은 크게 두가지인데

클래스 외부에서 호출, 두번째는 클래스의 기능을 추가하는 것이다

위의 people, student를 가지고 계속 설명하자면

student A;
 people \*B = &A
 B->f();
 B->people::f();

student A를 선언하고

people *B=&A; //A의 주소를 B에 넣는다

B->f()를 하게 되면 재정의된 f,즉 파생 클래스인 student의 f가 실행된다

b->people::f()를 하게 되면 기본클래스의 맴버인 f()가 실행된다

이로써 오버라이딩과 동적 바인딩에 알아보았다

업데이트: