개발자 '쑥말고인절미'

[C++]가상함수, 소멸자에 virtual 본문

STUDY/C++ & MFC

[C++]가상함수, 소멸자에 virtual

쑥말고인절미 2022. 6. 10. 10:42
가상함수를 쓰는 이유 중 하나는 엉뚱한 소멸자가 호출되는 것을 막기 위함이다.

 

  • 가상함수는 부모 클래스에서 상속받을 클래스에서 재정의할 것으로 기대하고 정의해놓은 함수이다.
  • virtual이라는 예약어를 함수 앞에 붙여서 생성할 수 있으며 이렇게 생성된 가상함수는 파생 클래스에서 재정의하면 이전에 정의되었던 내용들은 모두 새롭게 정의된 내용들로 교체된다.
  • 부모 클래스의 소멸자에 virtual을 작성하지 않으면 부모 클래스가 소멸될 때 자식 클래스의 소멸자는 호출되지 않아 메모리에 남게 된다.
  • 그렇기 때문에 부모 클래스의 소멸자에 virtual을 작성하여 부모 클래스 소멸 시 자식 클래스의 소멸자부터 호출되게 해주는 것이다.

+ 24.08.03 내용추가

가상 함수
#include <iostream>
using namespace std;

class Base {
public:
    virtual void show() {  // 가상 함수
        cout << "Base class show function called" << endl;
    }
};

class Derived : public Base {
public:
    void show() override {  // 재정의된 함수
        cout << "Derived class show function called" << endl;
    }
};

int main() {
    Base* b;
    Derived d;
    b = &d;

    b->show();  // Derived class의 show() 함수가 호출됩니다.

    return 0;
}

// 출력 결과
Derived class show function called
  • 객체지향 개념 중 다형성이 virtual 개념이다. 가상 함수(virtual method)를 사용하면 파생 클래스의 객체를 통해 기본 클래스의 참조 또는 포인트를 사용하여 올바른 함수가 호출되도록 할 수 있다.
  • 위 소스의 메인문에서
    • 부모 클래스인 Base 포인트 객체 b 생성
    • 자식 클래스인 Derived 객체 변수 d 생성
    • 부모 클래스 포인트 변수인 b에 자식 클래스 변수 d의 주소값을 정의
    • 포인트 변수인 b는 d의 주소값을 가르키기 때문에 show()는 부모 클래스가 아닌 자식 클래스에 재정의된 show()가 호출된다.
  • 이와 같이 가상 함수를 사용하면 상속 관계에 있는 클래스들이 서로 다른 구현을 가지면서도, 공통된 인터페이스를 통해 일관된 방법으로 사용할 수 있게 된다.
가상 소멸자
  • 가상 소멸자는 C++에서 매우 중요한 개념으로, 기본 클래스의 소멸자가 가상 함수로 선언된 경우에 사용된다. 이렇게 하면 파생 클래스 객체를 삭제할 때 올바른 소멸자가 호출되도록 보장할 수 있다.
  • 기본 클래스의 포인터를 사용하여 파생 클래스 객체를 삭제할 때, 기본 클래스의 소멸자가 가상 함수로 선언되지 않으면, 파생 크래스의 소멸자가 호출되지 않고 기본 클래스의 소멸자만 호출된다. 이렇게 되면 파생 클래스에서 동적 할당된 자원이 제대로 해제되지 않을 수 있다. 이를 방지하기 위해 소멸자를 가상 함수로 선언한다.
#include <iostream>
using namespace std;

class Base {
public:
    virtual ~Base() {  // 가상 소멸자
        cout << "Base destructor called" << endl;
    }
};

class Derived : public Base {
public:
    ~Derived() {
        cout << "Derived destructor called" << endl;
    }
};

int main() {
    Base* b = new Derived();  // Derived 객체를 Base 포인터로 가리킴
    delete b;  // 올바르게 Derived 소멸자와 Base 소멸자가 호출됨

    return 0;
}

// 출력 결과
Derived destructor called
Base destructor called
  • 위 소스에서 부모 클래스의 소멸자가 가상 함수가 아니었다면, 자식 클래스의 소멸자는 호출되지 않았을 것이고, 이로 인해 메모리 누수 등 예상치 못한 문제가 발생할 수 있다. 이로 인해 메모리 누수 등 예상치 못한 문제가 발생할 수 있다.

참고링크

https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=marcryu&logNo=140064910366 

 

가상함수 쓰는 이유

그것은 엉뚱한 소멸자가 호출되는것을 막기 위해서입니다. C++은 자바와 달리 virtual을 키워드를 쓰지 않...

blog.naver.com

http://hyacinth.byus.net/moniwiki/wiki.php/C%2B%2B/%EC%86%8C%EB%A9%B8%EC%9E%90%EC%97%90%20virtual%EC%9D%84%20%EC%93%B0%EB%8A%94%20%EC%9D%B4%EC%9C%A0

 

C++/소멸자에 virtual을 쓰는 이유

먼저 상속을 받은 클래스의 생성과 소멸 과정을 보자. 생성자는 부모 클래스의 생성자에서 자식 클래스의 생성자 순서로 불려지고, 소멸자는 자식 클래스의 소멸자가 먼저 불려지고 나서 부모

hyacinth.byus.net

https://coding-factory.tistory.com/699

 

[C++] 가상함수(virtual) 사용법 총정리

가상함수란? 가상함수는 부모 클래스에서 상속받을 클래스에서 재정의할 것으로 기대하고 정의해놓은 함수입니다. virtual이라는 예약어를 함수 앞에 붙여서 생성할 수 있으며 이렇게 생성된 가

coding-factory.tistory.com