λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
NOTE/Programming

[C++] 가상 μ†Œλ©Έμž (Virtual Destructor) & μ‚¬μš© 이유

by DevAthena 2025. 4. 23.

🎯 핡심 μš”μ•½

클래슀의 상속을 μ‚¬μš©ν•  λ•Œ λΆ€λͺ¨ 클래슀의 μ†Œλ©Έμžκ°€ virtual이 μ•„λ‹ˆλ©΄,
μžμ‹ 클래슀 포인터λ₯Ό λΆ€λͺ¨ 클래슀 ν¬μΈν„°λ‘œ μ‚­μ œν•  λ•Œ,
μžμ‹ 클래슀의 μ†Œλ©Έμžκ°€ ν˜ΈμΆœλ˜μ§€ μ•Šμ•„μ„œ λ¦¬μ†ŒμŠ€ λˆ„μˆ˜κ°€ λ°œμƒν•  수 있기 λ•Œλ¬Έ.

 

πŸ” 상황 μ˜ˆμ‹œ

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Base {
public:
    ~Base() { std::cout << "Base destructor\n"; }
};
 
class Derived : public Base {
public:
    ~Derived() { std::cout << "Derived destructor\n"; }
};
 
int main() {
    Base* ptr = new Derived();
    delete ptr;  // β— λ¬Έμ œ λ°œμƒ!
}
cs

 

 

πŸ”₯ 좜λ ₯ κ²°κ³Ό

Base destructor

Derived의 μ†Œλ©Έμžκ°€ ν˜ΈμΆœλ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

λ§Œμ•½ Derivedμ—μ„œ λ™μ μœΌλ‘œ ν• λ‹Ήν•œ λ¦¬μ†ŒμŠ€κ°€ 있으면 λ©”λͺ¨λ¦¬ λˆ„μˆ˜κ°€ λ°œμƒν•˜λŠ” 것 μž…λ‹ˆλ‹€.

 

βœ… ν•΄κ²° 방법 및 κ²°λ‘ 

1
2
3
4
class Base {
public:
    virtual ~Base() { std::cout << "Base destructor\n"; }
};
cs

μ΄λ ‡κ²Œ ν•˜λ©΄ delete ptr μ‹œμ— 가상 μ†Œλ©Έμž 체인을 따라가며 Derived → Base μˆœμ„œλ‘œ μ†Œλ©Έμžκ°€ λͺ¨λ‘ ν˜ΈμΆœλœλ‹€.

즉, λ‹€ν˜•μ„±μ„ μ‚¬μš©ν•  경우 (Base* ptr = new Derived();) λΆ€λͺ¨ 클래슀의 μ†Œλ©ΈμžλŠ” λ°˜λ“œμ‹œ virtual둜 μ„ μ–Έν•΄μ•Ό μ•ˆμ „ν•©λ‹ˆλ‹€.

κ·Έλ ‡μ§€ μ•ŠμœΌλ©΄ μžμ‹ μ†Œλ©Έμžκ°€ ν˜ΈμΆœλ˜μ§€ μ•Šμ•„ λ©”λͺ¨λ¦¬ λˆ„μˆ˜, λ¦¬μ†ŒμŠ€ λˆ„λ½ λ“±μ˜ λ¬Έμ œκ°€ 생길 수 μžˆμŠ΅λ‹ˆλ‹€.

λ•Œλ¬Έμ—, 상속될 μ—¬μ§€κ°€ μžˆλŠ” Base ν΄λž˜μŠ€λ“€μ€ λ°˜λ“œμ‹œ μ†Œλ©Έμžλ₯Ό virtual둜 λ§Œλ“€μ–΄μ£ΌλŠ” μŠ΅κ΄€μ„ κΈ°λ₯΄λ©΄ μ’‹λ‹€.

 


 

πŸ’‘μΆ”κ°€ 팁

C++11 μ΄ν›„μ—λŠ” virtual ~Base() = default; 같이 default virtual μ†Œλ©Έμžλ„ 자주 μ“΄λ‹€.
좔상 클래슀의 경우 pure virtual μ†Œλ©Έμž virtual ~Base() = 0; 도 κ°€λŠ₯ν•˜κ³  κ΅¬ν˜„μ€ ν•„μˆ˜.

 

🎯default virtual μ†Œλ©Έμžλž€?

C++11λΆ€ν„°λŠ” μ†Œλ©Έμžλ₯Ό μžλ™ μƒμ„±ν•˜λ©΄μ„œλ„, κ°€μƒμœΌλ‘œ λ§Œλ“€ 수 μžˆλ‹€.

 

πŸ” μ„€λͺ…

1
2
3
4
class Base {
public:
    virtual ~Base() = default;
};
cs
virtual λ‹€ν˜•μ„± μ‚¬μš© μ‹œ μžμ‹ μ†Œλ©Έμžλ„ μ•ˆμ „ν•˜κ²Œ 호좜되게 함
= default μ»΄νŒŒμΌλŸ¬κ°€ μ†Œλ©Έμž 본문을 μžλ™μœΌλ‘œ λ§Œλ“€μ–΄μ€Œ (λ‚΄μš© μ—†μŒ)

 

즉, 이 μ†Œλ©Έμžκ°€ 가상이어야 ν•˜κ³ , 별도 λ‚΄μš©μ€ λΆˆν•„μš” ν•˜λ‹ˆ μ»΄νŒŒμΌλŸ¬κ°€ μ•Œμ•„μ„œ κΈ°λ³Έ μ†Œλ©Έμžλ₯Ό λ§Œλ“€μ–΄μ€˜! λΌλŠ” λœ»μ΄λ‹€.

 

그럼 이건 μ–Έμ œ μ‚¬μš©ν•˜λŠλƒ?

보톡 좔상 클래슀, μΈν„°νŽ˜μ΄μŠ€ μ—­ν•  ν΄λž˜μŠ€μ—μ„œ 별도 λ¦¬μ†ŒμŠ€ μ •λ¦¬λŠ” μ—†κ³  μžμ‹ μ†Œλ©Έμžκ°€ μ œλŒ€λ‘œ 호좜되게만 ν•˜κ³  싢을 λ•Œ μ‚¬μš©ν•œλ‹€.

 

μ˜ˆμ‹œλ‘œ, μ•„λž˜μ™€ 같은 λ•Œ μ‚¬μš©ν•œλ‹€κ³  λ³Έλ‹€.

1
2
3
4
5
class IAnimal {
public:
    virtual void speak() = 0;
    virtual ~IAnimal() = default;
};
cs

 


 

πŸ’¬ μΆ”κ°€ ꢁ금증

κ·Έλ ‡λ‹€λ©΄ = default, = delete, = 0
각각이 μ–΄λ–¨ λ•Œ 쓰이고, μ–΄λ–»κ²Œ λ‹€λ₯ΌκΉŒ?

 

C++μ—λŠ” νŠΉμˆ˜ν•œ ν•¨μˆ˜ μ„ μ–Έμžκ°€ μžˆλŠ”λ°, 이 3쒅을 비ꡐ해본닀면 μ•„λž˜μ™€ κ°™λ‹€.

ν‘œν˜„ 의미 μ˜ˆμ‹œ μ„€λͺ…
= default κΈ°λ³Έ κ΅¬ν˜„μ„ λͺ…μ‹œμ μœΌλ‘œ μš”μ²­ Base() = default; μ»΄νŒŒμΌλŸ¬κ°€ κΈ°λ³Έ μƒμ„±μž/μ†Œλ©Έμž 등을 μžλ™μœΌλ‘œ 생성
= delete μ‚¬μš© κΈˆμ§€ Base(const Base&) = delete; 볡사 μƒμ„±μžλ₯Ό κΈˆμ§€ν•΄μ„œ 볡사 λΆˆκ°€λŠ₯ν•˜κ²Œ λ§Œλ“¦
= 0 순수 가상 ν•¨μˆ˜(Pure Virtual) virtual void foo() = 0; μžμ‹ ν΄λž˜μŠ€κ°€ λ°˜λ“œμ‹œ κ΅¬ν˜„ν•΄μ•Ό 함 (좔상 클래슀)

 

πŸ”Ή = default

1
2
3
4
5
6
7
class A {
public:
    A() = default;                 // κΈ°λ³Έ μƒμ„±μž
    A(const A&= default;         // λ³΅μ‚¬ μƒμ„±μž
    A& operator=(const A&= default// λ³΅μ‚¬ λŒ€μž… μ—°μ‚°μž
    virtual ~A() = default;        // κΈ°λ³Έ virtual μ†Œλ©Έμž
};
cs
  • λ³Έλ¬Έ 없이 μ»΄νŒŒμΌλŸ¬κ°€ λ§Œλ“€μ–΄μ€Œ
  • 볡사/이동 μƒμ„±μž, μ†Œλ©Έμž 등에 자주 μ‚¬μš©
  • μ˜λ„λ₯Ό λͺ…ν™•ν•˜κ²Œ ν‘œν˜„ν•¨, 가독성에 μ’‹μŒ

πŸ”Ή = delete

1
2
3
4
5
6
class B {
public:
    B() = default;
    B(const B&= delete;              // λ³΅μ‚¬ μƒμ„±μž μ‚­μ œ
    B& operator=(const B&= delete;   // λ³΅μ‚¬ λŒ€μž… μ‚­μ œ
};
cs
  • ν•¨μˆ˜ 자체λ₯Ό κΈˆμ§€μ‹œν‚΄
  • 싱글톀, μœ ν‹Έλ¦¬ν‹° 클래슀 λ“±μ—μ„œ 볡사/이동 λ°©μ§€ν•  λ•Œ μ‚¬μš©
  • μ˜λ„μΉ˜ μ•Šμ€ μ‚¬μš©μ„ λ°©μ§€ (μ˜€λ²„λ‘œλ“œ 좩돌, μ˜λ„ν•˜μ§€ μ•Šμ€ ν˜• λ³€ν™˜)
  • ν˜ΈμΆœν•˜λ €ν•˜λ©΄ 컴파일 μ—λŸ¬!

πŸ”Ή = 0 

1
2
3
4
5
6
7
class Animal {
public:
    virtual void speak() = 0;  // μˆœμˆ˜ κ°€μƒ ν•¨μˆ˜
    virtual ~Animal() = 0;     // μˆœμˆ˜ κ°€μƒ μ†Œλ©Έμžλ„ κ°€λŠ₯ (단, κ΅¬ν˜„은 κΌ­ ν•΄μ€˜μ•Ό ν•¨)
};
 
Animal::~Animal() {}  // μ†Œλ©ΈμžλŠ” λͺΈμ²΄ κΌ­ μžˆμ–΄μ•Ό ν•¨!
cs
  • 순수 가상 ν•¨μˆ˜ 포함 → 객체 생성 λΆˆκ°€μ˜ 좔상 클래슀(섀계도)κ°€ 됨
  • μžμ‹ ν΄λž˜μŠ€κ°€ λ°˜λ“œμ‹œ override ν•΄μ•Ό 함
  • μΈν„°νŽ˜μ΄μŠ€ μ—­ν•  ν΄λž˜μŠ€μ—μ„œ μ‚¬μš©
  • κ΅¬ν˜„μ„ κ°•μ œ

 

 

 

 

'NOTE > Programming' μΉ΄ν…Œκ³ λ¦¬μ˜ λ‹€λ₯Έ κΈ€

[C++] Raw String Literal  (0) 2023.11.13
[C#] abstract(좔상) 클래슀의 μœ„ν—˜μ„±.  (0) 2018.04.01
[C#] Reflection && Attributes  (0) 2018.04.01
[C#] μ»¬λ ‰μ…˜  (0) 2018.04.01
[C#] μ˜ˆμ™Έμ²˜λ¦¬  (0) 2018.04.01