가상 함수와 추상 클래스

pjh5365·2023년 6월 13일
0

[C++]

목록 보기
2/6
post-thumbnail

가상 함수

가상 함수란 virtual 키워드로 선언된 멤버함수이다.
virtual은 컴파일러에게 자신에 대한 호출 바인딩을 실행시간까지 미루도록 지시하는 키워드이며 기본클래스나 파생클래스 어디에서나 선언될 수 있다.

오버라이딩

파생클래스에서 기본클래스의 가상 함수를 재정의 하는 것을 함수 오버라이딩이라 부른다.
함수가 오버라이딩 되면 업캐스팅하여 함수를 호출할 때 기본클래스의 함수가 아닌 파생클래스의 함수가 호출이 된다.
업캐스팅으로 원래의 함수를 호출하고 싶다면 오버라이딩이 아닌 함수 재정의를 사용하여야 한다.

함수 재정의와 오버라이딩의 차이

함수 재정의의 경우 업캐스팅하여 파생클래스인 B의 함수를 호출하더라도 포인터가 기본클래스인A의 포인터이므로 A의 함수가 호출된다.

함수 재정의

#include <iostream>

using namespace std;

class A {
public:
 void test() {
     cout << "기본클래스 함수실행" << endl;
 }
};
class B : public A {
public:
 void test() {
     cout << "파생클래스 함수실행" << endl;
 }
};

int main() {
 A a, *pa;
 B b, *pb;

 pa = &b;
 pa->test();
}

실행결과

기본클래스 함수실행

함수 오버라이딩의 경우 업캐스팅하여 파생클래스인 B의 함수를 호출하면 오버라이딩으로 기본클래스인 A의 함수가 무력화되어있기 때문에 오버라이딩 된 파생클래스인 B의 함수가 정상적으로 호출이 된다.

함수 오버라이딩

#include <iostream>

using namespace std;

class A {
public:
 virtual void test() {
     cout << "기본클래스 함수실행" << endl;
 }
};
class B : public A {
public:
 virtual void test() {
     cout << "파생클래스 함수실행" << endl;
 }
};

int main() {
 A a, *pa;
 B b, *pb;

 pa = &b;
 pa->test();
}

실행결과

파생클래스 함수실행

오버라이딩의 특징

  1. 가상 함수의 이름과 매개 변수 타입, 개수뿐 아니라 리턴 타입도 일치해야 오버라이딩이 성공한다.
  2. 가상 함수의 virtual 속성은 상속되는 성질이 있어 파생 클래스에서 virtual 키워드를 생략해도 자동으로 가상함수가 된다.

가상 소멸자

기본클래스의 소멸자를 만들 때 가상 함수로 작성할 것 을 권하는데 그 이유는 파생 클래스의 객체가 기본 클래스에 대한 포인터로 delete 되는 상황에서도 정상적인 소멸이 되도록 하기 위해서이다.
가상 함수로 만들게 되면 함수를 오버라이딩 한 것 처럼 소멸자를 오버라이딩 시키므로 파생클래스의 소멸자가 정상적으로 작동된 뒤 기본클래스의 소멸자가 작동한다.

오버로딩

오버로딩은 매개 변수의 타입이나 개수가 다른 함수들을 여러개 중복작성하는 것이다. 함수 중복은 상속관계에서도 존재할 수 있으며 기본 클래스의 멤버 함수와 이름은 같지만 매개 변수 타입이나 개수가 다른 함수를 파생클래스에서 작성할 수 있다.

순수 가상 함수

기본 클래스에서 작성된 가상 함수는 실행할 목적보다 파생클래스에서 재정의하여 구현할 함수를 알려주는 인터페이스 역할을 하며 파생클래스에서 가상 함수를 재정의한다면 동적 바인딩에 의해 기본 클래스의 가상 함수는 거의 실행되지 않는다. 따라서 굳이 기본클래스의 가상 함수에 코드를 작성할 필요가 없다.
함수의 코드가 없고 선언만 있는 가상함수를 순수 가상 함수라고 한다. 선언은 함수 원형 뒤에 =0;을 붙여 선언한다.

예시

class A {
public:
    virtual void f()=0;
}

순수 가상 함수는 코드를 가지지 않으므로 A 클래스의 구현부에 함수를 구현하면 안된다.

추상 클래스

최소 하나의 순수 가상 함수를 가진 클래스를 추상 클래스라고 말한다. 추상 클래스는 실행 코드가 없는 순수 가상 함수를 가지고 있기 때문에 불완전한 클래스이다. 그러므로 추상 클래스의 객체를 생성할 수 없다. 추상 클래스는 객체를 생성할 목적으로 만들지 않고, 상속을 위한 기본 클래스로 활용하는 것이 목적으로 일종의 인터페이스 역할을 한다. 추상 클래스의 모든 멤버 함수를 순수 가상 함수로 선언할 필요는 없으며 일반적으로 여러 멤버 변수와 여러 멤버 함수를 구현하고 나름의 기능을 가진다. 하지만 파생클래스에서 구현해야 할 함수는 순수 가상 함수로 선언한다. 추상 클래스를 상속받는 파생 클래스는 순수 가상 함수를 그대로 상속받기 때문에 자동으로 추상 클래스가 된다. 추상 클래스를 사용하면 프로그램의 설계와 구현을 분리할 수 있으며 계층적 상속 관계를 가진 클래스들의 구조를 만들 때 좋다.

0개의 댓글