다형성 = 가상함수
가상함수가 구현된 class는 memcpy할 경우 vfptr도 함께 복사됨.
함수의 복사는 복사 생성자, 대입 연산자를 이용하는 것이 좋음.
class Parent
{
int* pParent;
public:
Parent()
{
pParent = new int;
}
~Parent()
{
delete pParent;
}
};
class Child : public Parent
{
int* pChild;
public:
Child()
{
pChild = new int;
}
~Child()
{
delete pChild;
}
};
int main()
{
Parent* p = new Child;
delete p;
return 0;
}
소멸자를 virtual 선언하지 않을 경우, 위의 상황에서 pChild는 해제되지 않음.
메모리 누수 발생.
bool div(int a, int b, int* result)
{
if(b == 0)
return false;
result = a / b;
return true;
}
기존 함수에서의 예외처리는 return값을 통해 처리
전달할 수 있는 정보의 양이 한정적임.
class Exception
{
...
};
void func()
{
throw 1;
throw 3.0f;
Exception e;
throw e;
}
int main()
{
try
{
func();
}
catch(int i)
{
}
catch(float f)
{
}
catch(Exception e)
{
}
catch(...)
{
}
return 0;
}
다양한 정보 전달 가능.
값에 맞는 catch가 지정되어 있으면 문제 없음.
중첩된 catch의 경우 가장 가까운 catch로 이동.
catch 내부에서 throw도 가능(중계).
class Parent { };
class Child : public Parent { };
void func()
{
throw Child();
}
int main()
{
try
{
func();
}
catch(Parent p)
{
cout << "Parent" << endl; //Parent Catched
}
catch(Child c)
{
cout << "Child" << endl;
}
return 0;
}
catch 구문의 순서는 파생클래스부터 잡도록 해야함.
void func() throw(type1, type2);
함수의 정의부에 던질 예외를 미리 적어둘 수 있음.
구현과 달라도 상관은 없음.
cpp에서는 표준으로 정해둔 예외 클래스가 존재.
클래스에 필요 정보를 채워 클래스 단위로 예외를 보내는 것이 좋음.
--FILE-- : 파일의 전체 경로
--LINE-- : 현재 라인
--FUNCTION-- : 현재 함수 명
함수가 예외를 발생시키지 않는다면 noexception을 통해 함수 정의부에 명시.
실제로 예외를 던져도 문제는 없지만 예외 처리가 불가능.
컴파일러의 추가 최적화 수행.
cpp11부터 소멸자는 기본적으로 noexception.
void func2()
{
throw 'c';
cout << "Func2" << endl;
}
void func1()
{
func2();
cout << "Func1" << endl;
}
int main()
{
try
{
func1();
}
catch(char c)
{
cout << "Catch" << endl;
}
return 0;
}
throw된 exception은 가장 가까운 catch로 넘어가고 throw이후의 구문은 수행되지 않음.
위의 경우 Catch만 출력되고 Func1, Func2는 출력되지 않음.
void func2()
{
int* pInt = new int;
throw 'c';
cout << "Func2" << endl;
delete pInt;
}
void func1()
{
func2();
cout << "Func1" << endl;
}
int main()
{
try
{
func1();
}
catch(char c)
{
cout << "Catch" << endl;
}
return 0;
}
위의 상황에서 pInt는 해제되지 않음.
모든 리소스의 동적 할당은 생성자에서만 수행.
이를 통해 Stack Unwinding 과정에서 발생하는 Memory Leak 방지 가능.
클래스, 상속의 발생에 의해 추가됨.
상수성(const), 휘발성(volatile) 제거.
무조건 수행.
비트 재해석.
void*에서 쓸 수 있을 듯.
HashMap에서 사용?
c의 casting.
상속 관계.
런타임 검사 없음.
class Parent
{
void pFunc();
...
};
class Child : public Parent
{
void cFunc();
...
};
int main()
{
Parent* pParent = new Parent;
Child* pChild = static_cast<Child*>(pParent);
pChild->cFunc(); // 위험
다운캐스팅 가능 -> 위험
class AClass
{
public:
int m_iValue;
// BClass로 케스팅되는 방법을 알려준다.
operator BClass();
};
AClass::operator BClass()
{
// 멤버초기화
BClass fRet = { static_cast<float>(m_iValue) };
return fRet;
};
이 경우 static_cast가 가능.
상속 관계.
런타임 검사 수행. 실패시 NULL 반환.
부모에 virtual function 필수. type_id가 vfptr에 추가됨.
객체의 메모리를 참조하여 객체에 대한 정보를 얻는 것.
둘 다 큰 차이는 없는 듯.