산업 제조
산업용 사물 인터넷 | 산업자재 | 장비 유지 보수 및 수리 | 산업 프로그래밍 |
home  MfgRobots >> 산업 제조 >  >> Industrial programming >> C 언어

C++ 다형성 이해하기: virtual 함수와 순수 가상 함수

다형성(polymorphism)이란 여러 형태를 가짐을 의미합니다. 일반적으로 다형성은 클래스 계층이 있고 상속으로 연결되어 있을 때 발생합니다.

C++ 다형성은 멤버 함수 호출 시 해당 함수를 호출하는 객체 타입에 따라 다른 함수가 실행됨을 의미합니다.

기반 클래스가 다른 두 클래스로 파생된 다음 예제를 살펴보겠습니다.

Live Demo
#include <iostream>
using namespace std;
class Shape {
protected:
    int width, height;
public:
    Shape(int a = 0, int b = 0) { width = a; height = b; }
    int area() {
        cout << "Parent class area :" << endl;
        return 0;
    }
};
class Rectangle: public Shape {
public:
    Rectangle(int a = 0, int b = 0): Shape(a, b) { }
    int area() {
        cout << "Rectangle class area :" << endl;
        return (width * height);
    }
};
class Triangle: public Shape {
public:
    Triangle(int a = 0, int b = 0): Shape(a, b) { }
    int area() {
        cout << "Triangle class area :" << endl;
        return (width * height / 2);
    }
};
int main() {
    Shape *shape;
    Rectangle rec(10,7);
    Triangle tri(10,5);
    // Rectangle 주소 저장
    shape = &rec;
    // rectangle area 호출
    shape->area();
    // Triangle 주소 저장
    shape = &tri;
    // triangle area 호출
    shape->area();
    return 0;
}

위 코드를 컴파일하고 실행하면:

Parent class area :
Parent class area :

잘못된 출력이 나오는 이유는 area() 함수 호출이 컴파일러에 의해 기반 클래스에 정의된 버전으로 한 번 설정되기 때문입니다. 이를 정적 바인딩(static binding) 또는 정적 연결(static linkage), 조기 바인딩(early binding)이라 합니다. area() 함수가 프로그램 컴파일 중에 설정되기 때문입니다.

이제 프로그램에서 Shape 클래스의 area() 선언 앞에 virtual 키워드를 붙여 약간 수정해 보겠습니다.

class Shape {
protected:
    int width, height;
public:
    Shape(int a = 0, int b = 0) { width = a; height = b; }
    virtual int area() {
        cout << "Parent class area :" << endl;
        return 0;
    }
};

이 약간의 수정 후 이전 예제 코드를 컴파일하고 실행하면:

Rectangle class area
Triangle class area

이번에는 컴파일러가 포인터의 타입이 아닌 내용을 봅니다. tri와 rec 클래스 객체의 주소가 *shape에 저장되어 있으므로 각각의 area() 함수가 호출됩니다.

보시는 바와 같이 각 자식 클래스는 area() 함수에 대한 별도의 구현을 가집니다. 이것이 다형성이 일반적으로 사용되는 방식입니다. 같은 이름, 심지어 같은 매개변수를 가진 함수가 다른 클래스에 있지만 구현이 다릅니다.

가상 함수(Virtual Function)

가상 함수는 virtual 키워드를 사용해 기반 클래스에서 선언된 함수입니다. 기반 클래스에서 가상 함수를 정의하고 파생 클래스에서 다른 버전을 정의하면, 컴파일러에게 이 함수에 대해 정적 연결을 원하지 않음을 알립니다.

우리가 원하는 것은 프로그램의 주어진 시점에서 호출될 함수 선택이 그것이 호출되는 객체의 종류에 기반하는 것입니다. 이러한 유형의 작업을 동적 연결(dynamic linkage) 또는 후기 바인딩(late binding)이라 부릅니다.

순수 가상 함수(Pure Virtual Functions)

기반 클래스에 가상 함수를 포함시키고 싶지만, 그 함수에 대해 기반 클래스에서 의미 있는 정의를 내릴 수 없고 파생 클래스에서 해당 클래스 객체에 맞게 재정의되길 원할 수 있습니다.

기반 클래스의 가상 함수 area()를 다음과 같이 변경할 수 있습니다.

class Shape {
protected:
    int width, height;
public:
    Shape(int a = 0, int b = 0) { width = a; height = b; }
    // 순수 가상 함수
    virtual int area() = 0;
};

= 0은 컴파일러에게 함수가 본문이 없음을 알리며, 위 가상 함수는 순수 가상 함수(pure virtual function)라 불립니다.

C 언어

  1. C++ 연산자 마스터하기: 유형별 완벽 가이드와 실전 예제
  2. C++ 배열을 함수에 전달하는 방법: 실전 가이드
  3. C++ 클래스와 객체: 객체지향 프로그래밍 실전 가이드
  4. C++ 프렌드 함수와 프렌드 클래스: 접근 제어 마스터하기
  5. C++ 클래스 템플릿 마스터: 실전 가이드
  6. C++ 연산자 오버로딩 실전 가이드: 문법, 접근법, 코드 예제
  7. C++ 저장 클래스 완벽 가이드: 범위, 수명, 용법
  8. C++ 오버로딩 마스터하기: 함수 & 연산자 오버로딩 완전 정복
  9. C++ 데이터 추상화 마스터하기: 인터페이스와 구현 분리로 설계 단순화
  10. C++ 데이터 캡슐화: 코드 보호의 핵심 원리