[C++] 가상 함수 (Virtual function)

Woozard·2023년 5월 18일
2

C++

목록 보기
2/2
post-thumbnail

이 글에서는 가상 함수뿐 아니라 관련된 추상 클래스, 동적 바인딩 내용도 포함됩니다.

가상 함수 의미

가상 함수 (virtual function)는 파생 클래스에서 재정의될 멤버 함수를 의미합니다.

가상 함수 예제 및 설명


class A {
public:
    virtual void Print() { cout << "A 클래스 Print 함수" << endl; }
};

class B : public A {
    virtual void Print() { cout << "B 클래스 Print 함수" << endl; }
};

가상 함수는 함수 앞에 virtual 키워드를 사용하여 선언한다.
파생 클래스에서 재정의 할 때는 virtual 키워드 생략 가능

단순 가상 함수와 순수 가상 함수 차이점


class A {
public:
    virtual void Print() { cout << "A 클래스 Print 함수" << endl; }
    virtual void Show() = 0;
};

class B : public A {
    virtual void Print() { cout << "B 클래스 Print 함수" << endl; }
    virtual void Show() { cout << "B 클래스 Show 함수" << endl; }
};

위에 코드를 보면 Print()와 Show()가 있는 것을 볼 수 있다. 그리고 둘 다 virtual 키워드를 사용해서 선언했으니 가상 함수라는 것도 알 수 있다. 하지만 차이점은 Show()는 Print()와 다르게 '= 0';으로 선언 된 것을 볼 수 있다. 이런 식으로 작성하는 방식을 순수 가상 함수라고 하고 그렇지 않은 것을 일반(단순) 가상 함수라고 한다.
단순 가상 함수와 순수 가상 함수의 가장 큰 차이점은 단순 가상 함수는 파생 클래스에서 무조건 오버라이딩을 해줄 필요가 없지만, 순수 가상 함수는 오버라이딩이 강요된다.

추상 클래스 의미

추상 클래스는 한 개 이상의 순수 가상 함수를 포함한 클래스를 의미한다.

정적 바인딩과 동적 바인딩 의미

함수를 호출하는 코드에서 어느 블록에 있는 함수를 실행하라는 의미로 해석하는 것을 바인딩 (binding)이라고 한다. 대부분 함수를 호출하는 코드는 컴파일 타임에 고정된 메모리 주소로 변환되는데 이를 정적 바인딩 (static binding)이라고 한다. 하지만 가상 함수의 호출은 컴파일러가 어떤 함수를 호출해야 하는지 미리 알 수 없다. 왜냐하면, 가상 함수는 프로그램이 실행될 때 객체를 결정하므로, 컴파일 타임에 해당 객체를 알수 없기 때문이다. 따라서 가상 함수의 경우에는 런타임에 올바른 함수가 실행될 수 있도록 해야 하는데 이를 동적 바인딩 (dynamic binding)이라고 한다.
C++에선 가상 함수가 아닌 모든 멤버 함수는 정적 바인딩을 하게 된다.

정적 바인딩과 동적 바인딩 예제 및 설명


class A {
public:
    virtual void Print() { cout << "A 클래스 Print 함수" << endl; }
};

class B : public A {
    virtual void Print() { cout << "B 클래스 Print 함수" << endl; }
};

int main() {
	B b; //정적 바인딩 부분
    b.Print();
}
class A {
public:
    virtual void Print() { cout << "A 클래스 Print 함수" << endl; }
};

class B : public A {
    virtual void Print() { cout << "B 클래스 Print 함수" << endl; }
};

int main() {
	A* a = new B(); //동적 바인딩 부분
    a->Print();
}

첫 번째 코드를 보면 정적 바인딩을 할 때 우리가 흔히 아는 방식처럼 클래스에 대한 객체를 생성하는걸 볼 수 있다. 하지만 두 번째 코드를 보면 베이스 클래스의 포인터 객체를 생성하고 그 객체가 파생 클래스의 주소 값을 가지고 있는걸 볼 수 있다. 이러한 방식을 동적 바인딩이라고 한다.

profile
Hello, World!

0개의 댓글