κΈ€ μž‘μ„±μž: λ˜₯폴베.
λ°˜μ‘ν˜•

1. μ„€λͺ…


 C의 캐슀트 μ—°μ‚°μžλŠ” λ³€μˆ˜μ˜ νƒ€μž…μ„ λ°”κΏ€ 수 μžˆλ‹€λŠ” λ©΄μ—μ„œ νŽΈλ¦¬ν•˜κ³  μœ μ—°ν•œ μ½”λ“œ μž‘μ„±μ„ 도와쀀닀. ν•˜μ§€λ§Œ λ„ˆλ¬΄ λ¬΄μ±…μž„ν•˜κ³  κ°œλ°œμžμ—κ²Œ λͺ¨λ“  것을 λ– λ„˜κΈ΄λ‹€. C++μ—μ„œλŠ” μ’€ 더 μ•ˆμ „ν•˜κ³  λ³€ν™˜ λͺ©μ μ— 맞게 골라 μ“Έ 수 μžˆλŠ” 4개의 μƒˆλ‘œμš΄ 캐슀트 μ—°μ‚°μžλ₯Ό μ œκ³΅ν•œλ‹€.

 

  • static_cast

  • reinterpret_cast

  • dynamic_cast

  • const_cat

 

 

1.1) static_cast

static_cast μ—°μ‚°μžλŠ” μ§€μ •ν•œ νƒ€μž…μœΌλ‘œ λ³€κ²½ν•˜λŠ”λ° 무쑰건 λ³€κ²½ν•˜λŠ” 것이 μ•„λ‹ˆλΌ λ…Όλ¦¬μ μœΌλ‘œ λ³€ν™˜ κ°€λŠ₯ν•œ νƒ€μž…λ§Œ λ³€ν™˜ν•œλ‹€.

void main()
{
	const char* str = "korea";
	int* pi;
	double d = 123.456;
	int i;

	i = static_cast<int>(d);                  // κ°€λŠ₯
	pi = static_cast<int*>(str);            // μ—λŸ¬
	pi = (int*)str;                          // κ°€λŠ₯
}

 μ‹€μˆ˜ν˜•μ˜ dλ₯Ό μ •μˆ˜ν˜•μœΌλ‘œ μΊμŠ€νŒ…ν•˜κ±°λ‚˜ λ°˜λŒ€μ˜ κ²½μš°λ„ ν—ˆμš©λœλ‹€. κ·ΈλŸ¬λ‚˜ ν¬μΈν„°μ˜ νƒ€μž…μ„ λ‹€λ₯Έ κ²ƒμœΌλ‘œ λ³€ν™˜ν•˜λŠ” 것은 ν—ˆμš©λ˜μ§€ μ•ŠμœΌλ©° 컴파일 μ—λŸ¬λ‘œ μ²˜λ¦¬λœλ‹€.

 

 μœ„ν—˜ν•œ 캐슀트 연산을 컴파일 쀑에 μ•Œλ € 쀌으둜써 μ‹€μˆ˜λ₯Ό 방지할 수 μžˆλ‹€.

 

class Parent {};
class Child : public Parent {};

void main()
{
	Parent p, * ptrP;
	Child c, * ptrC;
	int i = 1;

	ptrP = static_cast<Parent*>(&c); // κ°€λŠ₯
	ptrC = static_cast<Child*>(&p); // κ°€λŠ₯ν•˜μ§€λ§Œ μœ„ν—˜
	ptrP = static_cast<Parent*>(&i); // μ—λŸ¬
	ptrC = static_cast<Child*>(&i); // μ—λŸ¬
}

 Parent와 ChildλŠ” 상속 관계에 μžˆλŠ” ν΄λž˜μŠ€λ‹€. 상속 관계에 μžˆλŠ” 클래슀 ν¬μΈν„°λΌλ¦¬λŠ” μƒν˜Έ νƒ€μž… λ³€ν™˜ν•  수 μžˆλ‹€. λΆ€λͺ¨ 객체의 λ²ˆμ§€λ₯Ό μžμ‹ 객체의 ν¬μΈν„°λ‘œ λ‹€μš΄ μΊμŠ€νŒ…(Down casting)ν•˜λŠ” 것은 μœ„ν—˜ν•˜μ§€λ§Œ static_castλŠ” μ‹€ν–‰ 쀑에 νƒ€μž… 체크λ₯Ό ν•˜μ§€ μ•ŠμœΌλ―€λ‘œ 이 λ³€ν™˜μ΄ μœ„ν—˜ν•˜λ‹€λŠ” κ²ƒκΉŒμ§€λŠ” λͺ¨λ₯΄λ‹ˆ 일단 ν—ˆμš©ν•œλ‹€.

 

 

1.2) dynamic_cast

 dynamic_castλŠ” 포인터끼리 ν˜Ήμ€ 레퍼런슀끼리 λ³€ν™˜ν•˜λŠ”λ°, λ°˜λ“œμ‹œ ν¬μΈν„°λŠ” ν¬μΈν„°λ‘œ λ³€ν™˜ν•΄μ•Ό ν•˜κ³  λ ˆνΌλŸ°μŠ€λŠ” 레퍼런슀둜 λ³€ν™˜ν•΄μ•Ό ν•œλ‹€. 포인터끼리 λ³€ν™˜ν•  λ•Œλ„ λ°˜λ“œμ‹œ 상속 계측에 μ†ν•œ 클래슀끼리만 λ³€ν™˜ν•  수 μžˆλ‹€.

 

 dynamic_castλŠ” static_cast와 달리 λΆ€λͺ¨ μžμ‹κ°„μ„ λ³€ν™˜ν•  λ•Œ λ‹€μš΄ μΊμŠ€νŒ…μ˜ 경우 무쑰건 λ³€ν™˜μ„ ν—ˆμš©ν•˜μ§€ μ•Šκ³  μ•ˆμ „ν•˜λ‹€κ³  νŒλ‹¨λ  λ•Œλ§Œ ν—ˆμš©ν•œλ‹€.

#include <iostream>

using namespace std;

class Parent
{
public:
    virtual void print_me() { cout << "I am Parent\n"; }
};

class Child : public Parent
{
private:
    int num;

public:

    Child(int anum = 1234) : num(anum) { }
    virtual void print_me() override { cout << "I am Child\n"; }
    void print_num() { cout << "Hello Child = " << num << endl; }
};


void main()
{
    Parent p, * ptrP, * ptrP2;
    Child c, * ptrC, * ptrC2;
    ptrP = &p;
    ptrC = &c;

    ptrP2 = dynamic_cast<Parent*>(ptrC); // μ—… μΊμŠ€νŒ… - μ•ˆμ „
    ptrC2 = dynamic_cast<Child*>(ptrP2); // λ‹€μš΄ μΊμŠ€νŒ… - κ²½μš°μ— 따라 λ‹€λ₯΄λ‹€
    cout << "ptrC2 = " << ptrC2 << endl;
    ptrC2 = dynamic_cast<Child*>(ptrP); // μΊμŠ€νŒ… λΆˆκ°€λŠ₯(nullptr)
    cout << "ptrC2 = " << ptrC2 << endl;
}
ptrC2 = 000000E4B9EFFA68
ptrC2 = 0000000000000000

λΆ€λͺ¨ ν΄λž˜μŠ€ν˜• 포인터가 λΆ€λͺ¨ 객체λ₯Ό 가리킀고 μžˆλŠ” 상황 일 λ•Œ μžμ‹ ν΄λž˜μŠ€ν˜•μœΌλ‘œμ˜ λ‹€μš΄ μΊμŠ€νŒ…μ€ μ•ˆμ „ν•˜μ§€ μ•Šμ€ λ³€ν™˜μ΄λ‹€. 이런 경우 μΊμŠ€νŒ…μ„ ν—ˆμš©ν•˜μ§€ μ•Šκ³  nullptr을 λ¦¬ν„΄ν•œλ‹€.

 

 dynamic_cast μ—°μ‚°μžμ˜ λ³€ν™˜ λŒ€μƒ νƒ€μž…λ“€λΌλ¦¬λŠ” 상속 관계에 μžˆμ–΄μ•Ό ν•˜κ³  μ΅œμ†Œν•œ ν•˜λ‚˜ μ΄μƒμ˜ 가상 ν•¨μˆ˜λ₯Ό κ°€μ Έμ•Ό ν•œλ‹€.

 

 λ ˆνΌλŸ°μŠ€μ— λŒ€ν•΄μ„œλ„ μΊμŠ€νŒ… ν•  수 μžˆλŠ”λ° 레퍼런슀의 κ²½μš°λŠ” μ—λŸ¬μ— ν•΄λ‹Ήν•˜λŠ” NULL을 리턴할 수 μ—†μœΌλ―€λ‘œ bad_cast μ˜ˆμ™Έλ₯Ό λ˜μ§„λ‹€.

  

 

 

1.3) const_cast

 const_cast 캐슀트 μ—°μ‚°μžλŠ” ν¬μΈν„°μ˜ μƒμˆ˜μ„±λ§Œ λ³€κ²½ν•˜κ³  싢을 λ•Œ μ‚¬μš©ν•œλ‹€.

μƒμˆ˜ μ§€μ‹œ 포인터λ₯Ό λΉ„μƒμˆ˜ μ§€μ‹œ ν¬μΈν„°λ‘œ μž μ‹œ λ°”κΎΈκ³  싢을 λ•Œ const_cast μ—°μ‚°μžλ₯Ό μ“΄λ‹€.

λ°˜λŒ€μ˜ κ²½μš°λ„ λ¬Όλ‘  이 μ—°μ‚°μžλ₯Ό μ‚¬μš©ν•  수 μžˆκ² μ§€λ§Œ λΉ„ μƒμˆ˜ μ§€μ‹œ ν¬μΈν„°λŠ” μƒμˆ˜ μ§€μ‹œ ν¬μΈν„°λ‘œ 항상 λ³€ν™˜ κ°€λŠ₯ν•˜λ―€λ‘œ 캐슀트 μ—°μ‚°μžλ₯Ό μ“Έ ν•„μš”κ°€ μ—†λ‹€.

#include <iostream>

using namespace std;

void main()
{
    char str[] = "string";
    const char* c1 = str;
    char* c2;

    c2 = const_cast<char*>(c1);
    c2[0] = 'a';
    
    cout << c2 << endl;
}
atring

 μƒμˆ˜ μ§€μ‹œ 포인터 c1은 λΉ„ μƒμˆ˜ μ§€μ‹œ 포인터 str을 별닀λ₯Έ μ œμ•½ 없이 λŒ€μž…λ°›μ„ 수 μžˆλ‹€.

μ΄λ ‡κ²Œ λŒ€μž…λ°›μ€ 포인터λ₯Ό λ‹€λ₯Έ λΉ„μƒμˆ˜ μ§€μ‹œ 포인터 c2에 λŒ€μž…ν•˜κ³ μž ν•  λ•ŒλŠ” c2=c1으둜 λ°”λ‘œ λŒ€μž…ν•  수 μ—†λ‹€.

두 ν¬μΈν„°μ˜ μƒμˆ˜μ„±μ΄ λ‹€λ₯΄λ©° c1이 κ°€λ¦¬ν‚€λŠ” 읽기 μ „μš© 값을 c2둜 λΆ€μ£Όμ˜ν•˜κ²Œ λ°”κΏ” 버릴 μœ„ν—˜μ΄ 있기 λ•Œλ¬Έμ΄λ‹€.

 

κ·ΈλŸ¬λ‚˜ 이 경우 c1이 κ°€λ¦¬ν‚€λŠ” λŒ€μƒ(졜초 λŒ€μž…λ°›μ€ str)이 λ³€κ²½ κ°€λŠ₯ν•œ λŒ€μƒμ΄λΌλŠ” 것을 ν™•μ‹€νžˆ μ•Œκ³  μžˆμœΌλ―€λ‘œ c1의 μƒμˆ˜μ„±λ§Œ μž μ‹œ λ¬΄μ‹œν•˜λ©΄ λŒ€μž… κ°€λŠ₯ν•˜λ‹€. μ΄λ•Œ const_cast μ—°μ‚°μžλ‘œ c1을 char *둜 μΊμŠ€νŒ…ν•  수 μžˆλ‹€.

 

 

 

1.4) reinterpret_cast

 reinterpret_cast μ—°μ‚°μžλŠ” μž„μ˜μ˜ 포인터 νƒ€μž…λΌλ¦¬ λ³€ν™˜μ„ ν—ˆμš©ν•˜λŠ” μƒλ‹Ήνžˆ μœ„ν—˜ν•œ 캐슀트 μ—°μ‚°μžλ‹€.

심지어 μ •μˆ˜ν˜•κ³Ό ν¬μΈν„°κ°„μ˜ λ³€ν™˜λ„ ν—ˆμš©ν•œλ‹€. μ •μˆ˜ν˜• 값을 포인터 νƒ€μž…μœΌλ‘œ λ°”κΎΈμ–΄ μ ˆλŒ€ λ²ˆμ§€λ₯Ό 가리킀도둝 ν•œλ‹€κ±°λ‚˜ ν•  λ•Œ 이 μ—°μ‚°μžλ₯Ό μ‚¬μš©ν•œλ‹€.

int *pi;
char *pc;
pi=reinterpret_cast<int *>(12345678);
pc=reinterpret_cast<char *>(pi);

 μ΄ μ—°μ‚°μžλŠ” 포인터 νƒ€μž…κ°„μ˜ λ³€ν™˜μ΄λ‚˜ 포인터와 μˆ˜μΉ˜ν˜• λ°μ΄ν„°μ˜ λ³€ν™˜μ—λ§Œ μ‚¬μš©ν•˜λ©° κΈ°λ³Έ νƒ€μž…λ“€λΌλ¦¬μ˜ λ³€ν™˜μ—λŠ” μ‚¬μš©ν•  수 μ—†λ‹€. 예λ₯Ό λ“€μ–΄ μ •μˆ˜ν˜•μ„ μ‹€μˆ˜ν˜•μœΌλ‘œ λ°”κΎΈκ±°λ‚˜ μ‹€μˆ˜ν˜•μ„ μ •μˆ˜ν˜•μœΌλ‘œ λ°”κΎΈλŠ” 것은 ν—ˆλ½λ˜μ§€ μ•ŠλŠ”λ‹€. 이럴 λ•ŒλŠ” static_cast μ—°μ‚°μžλ₯Ό μ‚¬μš©ν•΄μ•Ό ν•œλ‹€. 

 

 

 

 

2. 참고 및 좜처


http://soen.kr/
λ°˜μ‘ν˜•

'Language > C++' μΉ΄ν…Œκ³ λ¦¬μ˜ λ‹€λ₯Έ κΈ€

[C++11] keyword: static_assert  (1) 2020.07.23
[C++] keyword: enum class  (0) 2020.07.23
[C++] keyword: noexcept  (0) 2020.07.23
[C++11] keyword: constexpr  (0) 2020.07.23
[C++] keyword: using  (0) 2020.07.23