IT Language 연습실
C++ 공부하면서 정리한 것들 본문
매크로를 이용한 함수 와 매크로 상수 , 인라인. (mecro) (inline)
namespace
:: ~의 << ~으로
using 전역, 지역
bool 자료형
참조자의 이해
int &num2 = num1
int *ptr = &num2
참조자가 참조 할 수 있는 다양한 변수들
참조와 포인터의 의미
참조자의 활용
함수
함수의 반환형이 참조자인 경우
상수화된 변수
Cpp에서 maaloc 과 free
참조자를 이용한 new와 delete
C언의 라이브러리에 정의된 표준 입출력 함수들을 사용하기 위한 Cpp (cstdio, cstdlib, ctime)
C++에서 데이터 표현과 데이터 처리
Cpp 구조체에서는 함수 역시 담을 수 있다!?
구조체안에 매크로 상수를 enum으로 묶는다!?
구조체안에 정의하는 것이 부담된다면 enum을 namespace 소속으로 묶는다!?
구조체가 함수의 정의로 너무 커졌다 이럴때 원형은 구조체 안으로 정의는 밖으로 대신 누구의 함수이고 원형 함수가 어디에 있는지
정의된 함수의 인라인화
class와 구조체의 차이 1) struct 를 쓰냐 class 를 쓰냐 2) 다른 영역에서 정의된 변수나 함수의 접근을 할 수 있냐 없냐. 즉, 접근제어 지시자가 필요하냐 없냐
파일 분할 (헤더파일, 소스파일) (헤더파일 - 멤버함수의 선언 (함수원형) , 구조체, 멤버변수 등) (소스파일 - 함수 정의 된 )
파일 분할시 inline 함수의 사용 ( h 파일에 선언된 원형함수 그리고 소스파일에 정의된 함수몸체에서 함수 몸체를 inline으로 사용됐다면?)
객체에 대하여
클래스 내에서 멤버변수를 초기화하는 과정에서 const를 이용한 초기화가 안된다. << ?? const 로 해도 되는 것 같은데?
함수 호출 후 멤버변수를 const 상수로 하고 싶은데 불가능하다. << ?? 좀 더 알아봐야 할 것 같다.
클래스 내에 있는 멤버변수를 상수화 시키는 방법 -> 생성자에 있음. 일단 생성자에 있다는 것만 기억
정보은닉 (멤버변수를 private 로 선언하는 이유 선언후 다른 클래스가 해당 클래스에 있는 멤버변수에 접근하는 방법)
정보은닉 멤버 변수를 private로 선언하고, 해당 변수에 접근하는 함수를 별도로 정의하여, 안전한 형태로 멤버 변수의 접근을 유도하는 것을 정보은닉이라고 한다.
return에 대한 정확한 이해 reference 리턴
함수에서
const
1) 일반 변수에 const가 붙은 경우
2) 포인터 변수에 const가 붙은 경우 ex) const int *ptr , int * const ptr
3) reference에 const가 붙은 경우
3) const void function() { }
4) void function() const { }
생성자
해당 클래스에서 외부 클래스의 객체를 멤버변수로 사용하는 경우 멤버 이니셜라이저 (다른게 아님 그냥 똑같은 생성자)
해당 클래스에서 사용하는 멤버변수를 이니셜라이저로 초기화 하는 경우
1) &, const
디폴트 생성자
private 생성자와 public 생성자
소멸자
객체 배열, 객체 포인터 배열 (객체 배열 = 인자값 전달 x , 객체 포인터 배열 = 인자값 전달 o)
self reference
복사생성자(copy constructor) - 컴파일러에 의한 복사생성자(shallow copy constructor), 사용자 정의에 의한 복사생성자(deepcopy constructor)
explicit
shllow copy (얕은복사) deepcopy (깊은복사)
복사생성자가 호출되는 시점 - 1) 일반 객체 생성 2) 함수호출 3) 리턴(반환)
참조값이란 의미
l-value(변수) r-value (변수,상수)
복사생성자에서 const &의 의미 그리고 const 가 붙는 이유와 버전의 차이 >> 왜 컴파일러 버전에 따라 되는가 ~17~20까지는 되는데 그 밑으로는 안됨.
임시객체
const 함수오버로딩
friend (클래스 단위, 멤버함수 단위로 가냐)
함수를 호출했는데 그 함수는 내 친구이면 친구는 나의 멤버변수까지 접근 가능해. 멤버함수 단위
, static (정적변수),
// 1) static 쓰임이 함수 자체를 static으로 걸어서 사용할 수 있는 방법 static function case
// 2) static 쓰임이 멤버로 선언되어 사용할 수 있는 방법 static member case
// 2-2) 위 방법이 싫어서 한번에 선언과 동시에 초기화를 하고 싶어 const static
// 3) static 쓰임이 함수 내에서 사용할 떄의 방법 function in static case
상속 문법적 이해 ( 해당 클래스의 멤버는 해당 클래스의 생성자를 통한 초기화가 제일 좋음) (용어) ( 소멸자에서 기초 클래스와 유도 클래스)
(접근제어지정 방식 에서 protected) (상속 명시에서 public 과 protected, private) (상속 조건 is-a (~이다) 관계 has-a (~을 소유한다) 소유 관계)
객체 포인터 변수
함수 오버라이딩 (클래스 상속관계에 있을떄) 상속관계에서 무조건 이름이 같다고 오버라이딩 되는 것이 아님 매개변수의 개수와 타입도 보는데 다르다면 오버로딩이됨
가상함수
1) 입력 및 처리하는 컨트롤 클래스 와 저장 하는 클래스 << 뭔가 확장성이 안 좋아.
2) 상속이라는 걸 하게 됐고, 그 과정에서 기초 클래스는 상속 받은 클래스 즉, 유도 클래스 객체의 주소를 담을 수 있다.
3) 하지만 그 과정에서 저장된 유도클래스 객체 주소에 접근하여 함수를 호출했는데 호출이 되지 않고 에러가 발생돼
4) 그 에러의 원인은 컴파일러는 포인터가 자료형에 맞게 (클래스에 맞게) 함수를 사용할 수 있게 했다는 것으로 접근만 가능하고
기초 클래스의 객체가 유도 클래스의 객체의 멤버 함수를 사용하려고 하면 클래스 타입이 다르니까 사용할 수 없어! 라는 에러를 발생시킴
5) 그 문제를 해결하기 위해 오버라이딩이라는 개념이 등장. 상속 받은 클래스 내에서 기초 클래스와 이름이 동일한 함수가 있고
기초 클래스는 이름이 동일한 함수의 호출을 원하고 있다면 클래스에 맞는 함수를 호출시켜 << 오버라이딩
6) 근데 나는 때려죽어도 기초 클래스가 가리키는 유도 클래스 객체의 멤버 함수를 호출시켜야겠어
즉, 자료형에 상관없이 가리키고 있는 함수를 호출시켜야겠어 라면 virtual 이란 키워드를 적어 가상함수 선언을 해주면 됨.
가상함수를 사용하기 위해 오버라이딩의 개념이 꼭 필요함
그럼 이제 오버라이딩의 개념 없이 독립된 가상함수를 사용할 수 있게 뭔가 있지 않을까? 라는 추측을 할 수 있음.
순수 가상함수 (함수가 정의되지 않은 부분 가상함수에 const = 0; 혹은 =0 이라고 붙혀주면 완전하지 못한 함수가 되어 객체 생성은 할 수 없음)
왜냐하면 하나의 순수 가상함수가 있는 것은 추상화클래스가 되고 추상화 클래스는 불완전한 클래스로 간주하여 컴파일러가 이 클래스로부터는
객체를 생성할 수 없어요라고 인식하기때문.
추상클래스 = 하나 이상의 순수 가상함수가 선언되어 있는 클래스로 객체생성이 불가한 클래스 완전하지 않은 클래스
다형성 = 문장은 같은데 결과는 다르다.
가상소멸자 -
상속관계의 소멸자 우선순위는 제일 하위 클래스 먼저 -> 부모 클래스
상속관계의 생성자 우선순위는 맨 위 부모 클래스 먼저 -> 하위 클래스
소멸자의 경우 포인터로 선언하여 지우려고 한다면 자료형을 따짐. 그래서 자료형에 맞는 소멸자만 호출하여 그것만 삭제
그래서 virtual 자료형에 상관없이 지울 수 있도록 해야 함. 메모리 누수가 발생하니깐
virtual을 붙히면 일단 그 포언티 자료형에 맞는 소멸자가 호출이 되는데 vritual이 붙어있는걸 확인후
아 가리키는 걸 그냥 지우라는 얘기구나로 인식하면서 포인터가 가리키는 소멸자로 가서 소멸시킨 후 부모 클래스의 객체도 소멸.
상속간 객체 참조자.
함수포인터 =
모든 함수에는 주소를 갖고 있다.
포인터변수가 함수의 주소를 담아서 그 함수를 가리켜 호출하는 형태가 함수 포인터를 의미하는데
1) 반환값이 어떤 형인지
2) 매개변수에서 인자를 받을때 어떤 형으로 받고 있는지
예를들어 int sum (int, int) 라는 함수가 있는데
int (*fp) (int, int) 이건 함수포인터야 << fp라는 포인터변수는 함수의 주소를 받을 수 있는데 이때 반환형과 매개변수 타입,개수가 같아야돼
int (*fp) (int,int) = sum;
혹은
int (*fp) (int,int) ;
*fp = sum;
그래서 함수포인터는 일단 반환형과 매개변수 개수 및 타입에 맞는 함수의 주소를 받고 그 다음 함수포인터변수를 사용해 그 주소가 가리키는 함수를 호출한다.
가상테이블
다중상속
가상상속 -
A라는 기초클래스로부터 상속받는 클래스가 B, C가 있었다.
B와 C를 다중상속을 받는 유도클래스 D는 B와 C 다중 상속으로 인해서 A라는 기초클래스를 간접 상속 두번하게 되는 거고
D가 상속받은 멤버를 사용하는데 있어서 어느 놈의 멤버를 사용할지 몰라 범위지정을 명시해주지 않으면 사용할 수 없게된다.
이러한 불편함을 B와 C가 A 클래스를 상속받을때 상속 명시를 virtual public A 라고 즉, virtual 키워드를 써주게 되고
그것을 D가 상속 받는다면 동일한 클래스로부터 상속받는 멤버를 한번만 상속해 ! 라고 하는 것이다.
그래서 D는 A클래스를 간접적으로 한번만 상속받게 되는 것이다.
또한 B와 C가 A의 생성자를 호출한다면 먼저 생성자가 호출된 쪽으로 A는 한번만 생성자가 호출된다.
연산자 오버로딩 (멤버함수 기반의 연산자 오버로딩, 전역함수 기반의 연산자 오버로딩(friend)) << 이항연산
단항 연산 오버로딩 (멤버함수 기반, 전역함수 기반)
이항이든 단항이든 전역함수기반은 연산자 자체 함수를 전역으로 처리했기때문에 객체가 함수를 호출하지 않음 this 사용 불가.
전위증가, 전위감소, 후위증가,후위감소
전위증가 및 감소는 operator()
후위증가 및 감소는 operator(int) << int를 적어주는 것으로 약속됨. 매개변수의 인자값을 전달하겠다는 것과는 상관없고. 그냥 전위인지 후위인지 구분을 위해 int를 사용.
int가 있다면 후위 없다면 전위
전역으로 후위를 하고 싶다면
operator(인자, int)
후위증감이나 후위감소 반환형에서 const 를 쓴 이유
복사생성자를 통해서 임시객체가 반환이 되고 반환시 const가 붙어 임시객체의 쓰기권한을 없애겠다. 임시객체의 멤버변수 변경 x
그래서 그 임시객체는 const가 붙어 const가 붙은 함수가 호출이 가능하고
또한 처음 실행이 될때만 처음 증감소 연산은 실행하지만 그 다음 반환이 된 이후에는 증감소 연산을 하지 않겠다라는 의미를 사용하기 위해서.
연산자 오버로딩 과정에서 교환법칙 성립시키기
1 + 2 = 3 , 2 + 1 = 3 인것처럼 피연산자의 위치가 바뀌더라도 결과는 같다는 법칙이 교환법칙 성립시키는 것이다.
교환법칙을 성립시키기 위해서는 operator 함수를 전역으로 사용하는 방법이 있다.
리턴 반환과정에서 operator 멤버함수를 호출을 하든 전역의 operator를 두개 작성하여 매개변수쪽에서 다르게 가든 그렇게 하는 방법이 있다라는 거.
cout, endl, cin 은 표준입출력헤더파일에 정의된 놈들임. 그것이 iostream
그 표준입출력을 들어다보면 std라는 소속의 ostream 이라는 클래스 형으로 cout 이 객체로 만들어져 있고
cout 을 연산할때 << 쉬프트 비트 연산자를 통해서 하게 되는데 이때 연산자 오버로딩이 됨
입출력에는 정수, 문자, 문자열, 실수, 등등 정의되어 있고 클래스나 구조체 같은 경우에는 정의되어 있지 않아 오버로딩을 따로 정의해줘야 하는 것임.
멤버함수기반의 경우 보통 객체 << 객체 로 가는 경우가 많음.
근데 cout 도 객체인데도 불구하고 전역으로 사용헀던 이유는 ostream 클래스 내에서 멤버함수를 따로 하나 더 정의 해야 되는데 힘들고 복잡합. 불가능함.
그럼 전역기반의 연산자 오버로딩 방법을 사용할 수 밖에 없음.
그리고 endl 블로그에 기술하겠음.
대입연산자 중에서 = 이거를 operator 연산자 오버로딩을 하게 된다면
복사생성자와 유사한 동작을 함.
디폴트 복사생성자 (shallow copy) 와 사용자가 정의한 복사생성자 (Deep copy) 가 있었듯이
대입연산자 중에서도 따로 명시를 하지 않았다면 디폴트 대입연산자가 호출이 되고 정의를 했다면 사용자가 정의한 대입연산자가 나와
shallow copy 혹은 deep copy 를 선택하게 되며, 동적할당시에 발생되는 문제도 같게됨.
대입연산자는 생성자가 아니라는 사실을 기억하고 있어야함.
상속관계에서 유도클래스의 생성자가 호출되고 그 안에서 기초 클래스 생성자 호출에 대한 어떤 명시도 없었다 해도 100프로 호출되는 관계기 떄문에
별도 명시가 없어도 기초 클래스의 생성자가 호출됐었다.
하지만 대입연산자는 생성자가 아니기 때문에 유도클래스 안에서 따로 명시가 없다면 기초클래스의 대입연산자는 호출되지 않는다.
즉, 위 경우는 다음의 경우를 말하는 것이다. 만일에 다음과 같은 경우라면?
기초클래스에 대입연산자가 정의되었고 유도클래스에는 정의되어 있지 않다면.
유도클래스에는 디폴트 대입연산자가 호출이될테고 기초클래스는 유도클래스의 디폴트 대입연산자가 호출하여 기초클래스의 대입연사자도 실행이됨
유도클래스와 기초클래스 둘다 대입연산자가 정의됐다면 유도클래스에서 기초클래스의 대입연산자를 호출하지 않았다면 유도클래스의 대입연산자만 실행이 된다.
따라서 만약 A 클래스가 기초클래스라고 치고 B클래스가 유도클래스라고 가정해보면
A::operator=(참조하고 있는 전달될 인자); 라고 명시를 해줘야 한다는 것이다. 단 상속관계에서!!! 반드시 직접 상속이든 간접 상속이든 받은 상태에서!!
대입연산과 복사생성자 과정에서 복사생성자의 호출 => (동적할당의 경우) (이니셜라이져를 통한 경우)를 추가로 알게됐음. 그걸 블로그에 기술하겠음.
배열 연산자 오버로딩 ( 배열 클래스 )
배열의 복사생성자와 대입연산자 오버로딩을 하게 두는 것보다는 배열의 저장된 값의 데이터 유일성을 보장하기 위하여 private으로 두고 원천적으로 막는것이 좋음.
기본자료형에 대한 배열 클래스
객체 저장을 위한 배열 클래스
객체 주소 저장을 위한 배열 클래스
포인터 배열과 이중포인터.
연산자 오버로딩 2 part 부분에서 특히 463 ~ 468page 상당히 어려워했음.
템플릿
템플릿을 파일분할 원칙에 맞게 분할하였다. 그러나 컴파일 에러가 나는 이유는 템플릿은 일반 함수, 클래스와는 다르게
h파일에 선언된 선언부 말고도 cpp 소스파일에 정의된 정의부분까지 정보를 필요로하게 된다.
따라서 선언부와 정의부분의 정보 모두 필요로 하기 때문에 메인에서 헤더파일만 읽어올게 아니라 템플릿이 정의된 cpp 파일까지 읽어와야 한다.
아니면 h파일에 템플릿이 정의된 부분까지 한번에 넣어두도록 하자.
(템플릿 컴파일 과정에서 정보가 부족하다는 이유는 ->
템플릿은 클래스나 함수를 자료형에 맞게 사용하기 위해서 사용자가 임의로 정의한 것이지 않은가?
그렇다면 컴파일은 헤더 부분만 읽어왔다면 자료형에 맞게 사용할 수 있게 하기 위해서는 당연히 정의부분도 알아야 한다.
그런데 정의부분이 생략된다면 어떤 자료형이 왔는데 그 자료형에 맞게 처리하게 하기 위해서는 부족하다는 것.
또한 함수 오버로딩이나 함수 오버라이딩을 하는 과정에서도 자료형이 명확해야 하는데 템플릿은 자료형이 없다. 명확하지 않다.
그래서 정보가 부족하다는 것. 정의부분을 꼭 알고 있어야 한다는 것
일반함수나 일반 클래스가 되는 것도 자료형 부분이 명확했기 때문이다)
스마트 포인터
클래스 템플릿 기반으로 컴파일러가 만든 템플릿 클래스의 객체를
또다른 클래스 템플릿 기반으로 컴파일러가 만든 템플릿 클래스가 받기.
클래스 템플릿의 특수화
클래스 템플릿의 부분 특수화 -
예를 들어서 T1과 T2로 자료형이 정의되어 있지 않고 사용됐는데 T1에 대해서만 자료형을 정의했다면
A 클래스 템플릿인데 T1에 대해서만 정의된 클래스 템플릿 기반으로 컴파일러가 템플릿 클래스를 생성.
혹은 A 클래스 템플릿인데 T2에 대해서만 정의된 클래스 템플릿 기반으로 컴파일러가 템플릿 클래스를 생성.
그게 class A <typename t2> or class A <typename T1> 이 될 수 있다.
만약 부분특수화와 전체 특수화가 같이 정의가 되어 있는 상황에서 둘다 조건을 만족하는 상황이라면 전체특수화가 우선적 처리.
클래스 템플릿의 매개변수로 변수선언 (매개변수의 변수선언도 템플릿 생성하고 그 생성된 템플릿 클래스를 불러내는데 있어서 영향을 준다는것.)
클래스 템플릿 매개변수의 디폴트 값. (대신 템플릿 클래스 객체를 생성할떄도 <> 라는 명시를 해줘야함.!!) 함수 템플릿 기반의 템플릿 함수와 차이.
템플릿에서 static 사용하기. (함수 템플릿, 클래스 템플릿)
try, catch, throw,
stack unwinding (스택풀기) - 함수 내에서 예외가 발생됐고 그 예외를 처리할 수 없어서 함수를 호출한 곳으로 예외 데이터를 전달하는 현상을 말함.
왜 그런 이름이 붙었을까?
모든 함수는 호출을 하게되면 메모리 스택에 함수가 push된다. 그리고 throw를 통해 예외를 발생시켰다. 하지만
그 함수는 예외를 처리할 수 없다면 함수를 호출한 곳으로 전달하게 되면서 함수는 종료가 된다. 그렇게 예외를 발생시킨 함수는 스택에서 POP 되고
다음 함수가 받고 처리할 수 없다면 또 처리할 수 있는 함수를 만날때까지 POP된다.
이러한 예외 데이터의 전달과정을 가리켜 스택풀기 (스택반환)이라고 그러는 것이다.
예외 데이터와 catch의 매개변수?는 서로 자료형이 일치해야 예외 데이터 처리가 가능하다. 하지만 일치하지 않다면
예외 데이터를 처리할 수 없음으로 처리가 가능한 곳으로 전달된다. 처리가 불가능하다면 종료됨...
따라서 하나의 try에 여러개의 catch가 존재할 수 있다.
일반 함수를 선얼할때 발생할 수 있는 예외 데이터에 대해서 명시를 가능하게 해준다.
ex) void function( ) throw (int, char) { } >> 함수 내에서 int 나 char 예외 데이터가 전달 될 수 있다, 만일에 int 나 char 말고 다른 타입이 전달되면 unexpected()함수 호출
ex) void function() throw( ) { } >> 함수 내에서 예외 데이터가 전달될게 없다. 만약 전달이 된다면 unexpected() 함수 호출 .
unexpected 함수의 호출은 곧 terminate () 함수를 호출하여 종료.
예외 클래스, 예외 객체, 예외 다시 던지기.
c스타일, cpp 스타일 다 통털어서 모든 형변환은 원본의 형이 바뀌는게 아니라 거기 형변환을 하는 문장에서만 유효.
형변환 연산자 ( dynamic_cast , static_cast , const_cast, reinterpret_cast, bad_cast)
dynamic cast 상속관계에서 안정성을 컴파일러가 보장하며 바꾸는 형변환 연산자.
(유도클래스의 포인터나 참조 데이터들을 기초 클래스의 형으로 변환한다.)
근데 dynamic cast가 기초 클래스의 포인터나 참조데이터들을 유도클래스의 형으로 변환하고 싶다면 다음의 조건을 만족해야 한다.
기초클래스의 하나 이상의 가상함수가 생성이되어 Polymorphic 클래스라는 사실을 명시해줘야 한다.
(Polymorphic 클래스 - 하나 이상의 가상함수를 갖고 있는 클래스) (추상화 클래스 - 하나 이상의 순수 가상함수를 갖고 있는 불완전한 클래스, 객체생성불가)
기초클래스의 포인터 가 가리키는 것이 동적할당된 기초클래스의 객체 주소일 경우
또 그런 기초클래스의 포인터를 유도클래스의 포인터 형으로 변환하려는 경우 유도클래스는 기초클래스의 주소를 받거나 참조 할 수 없다 따라서 NULL값이 반환된다.
static cast 기본 자료형이나 상속관계에 있는 객체들을 대상으로 형변환을 진행하는 연산자.
(상속관계에서 유도클래스의 포인터나 참조 데이터들의 형 변환 뿐만 아니라 기초클래스의 포인터나 참조 데이터들을 유도클래스로 바꿀 수도 있다.)
(기초클래스의 포인터가 가리키는게 유도클래스의 데이터라면 기초클래스의 포인터를 유도클래스로 바꿀 수 있고
기초클래스의 포인터가 가리키는게 기초클래스의 데이터라면 기초클래스의 포인터를 유도클래스로 바꿀 수 있다.
즉 그에 따른 책임은 개발자가 지게 된다.)
static_cast 가 dynamic_cast 보다 빠른 이유는 dynamic_cast는 안정적으로 형변환을 진행시키기 위해 컴파일러가 컴파일 이전에 안정성 검사를 위한 바이너리 코드를 생성한뒤 컴파일을 진행하는 과정을 겪어 실행 결과의 속도가 느리다.
하지만 static_cast 는 그러한 안정 여부와 상관없이 형변환을 시키기 때문에 그로인한 책임은 개발자가 지게 되는 것이다. 따라서 실행속도는 빠르다는 장점이 있다.
그렇기 떄문에 static이 dynamic 보다 빠른 이유이다.
const_cast : const를 제거.
보통 함수의 인자를 전달하는 과정에서 const로 선언된 변수를 함수의 인자로 전달하는 과정에서 전달 받을때 const가 없다면 전달 받을 수 없다.
const의 영향으로 형이 불일치하기 때문에 하지만 이떄
const_cast를 사용해서 const를 제거하여 보낸다면 자료형의 일치로 함수의 인자로 전달도 되고 받을 수도 있게 된다.
하지만. 그렇게 전달 받은 과정에서 만약 참조자나 포인터로 받았다면 메인에서 const로 선언된 변수의 값이 바뀔 수 있게 된다.
reinterpret_cast : reinterpret 단어 뜻 자체가 재해석, 새롭게 해석하다 라는 뜻을 갖고 있음. (포인터형과 관련된 거)
bad_cast : 프로그래머가 발생시킨 예외가 아닌 발생된 예외. dynamic 을 참조자로 사용하는 과정에서 발생될 수 있다.
dynamic_cast로 형변환을 진행하는 과정에서
Polymorphic 클래스라고 가정하에 기초 클래스를 객체를 하나 생성하고 그렇게 생성된 기초클래스의 객체를 참조할 수 있는 참조가 객체를 하나 만들고
참조자 객체를 유도클래스의 형으로 변환하려고 하는 과정이다. 하지만 유도클래스는 기초클래스 객체의 주소를 받을 수도 참조할 수 없다.
만약 포인터였다면 NULL 값을 반환하겠지만 참조자일 경우에는 NULL값을 반환하지 않는다.
이때 자동으로 throw 없이 자동으로 예외가 던져지는데 이것이 bad_cast이다.
따라서 참조형으로 dynamic_cast를 진행하려고 한다면 bad_cast 를 고려해서 사용해야 하며 그렇기 때문에 try{ } catch (bad cast 변수) { } 예외처리를 꼭 해줘야 한다.
'C++' 카테고리의 다른 글
C++ split( ) (0) | 2024.03.23 |
---|---|
고용, 정규, 영업, 임시직 관련 된 클래스 만들기 (0) | 2024.02.25 |
C++ 스타일에 맞는 형변환 (0) | 2024.02.25 |
template (4) 클래스 ver (0) | 2024.02.23 |
스마트 포인터 (Smart Pointer) (0) | 2024.02.22 |