본문 바로가기

전체 글57

항목 14. 자원 관리 클래스의 복사 동작에 대해 진지하게 고찰하자 우리는 RAII 기법 그리고, Heap 기반 자원에 대해 이 아이디어를 적용한 auto_ptr, tr1::shared_ptr 클래스에 대해서 공부하였다. Q. 하지만 힙기반 자원이 아닐땐 어떻게 해야할까? A. Mutex 객체를 조작하는 c api 함수인 lock과 unlock에대해 살펴보자. void lock(Mutex *pm); // pm이 가리키는 뮤텍스에 잠금을 건다. void unlock(Mutex *pm); // pm이 가리키는 뮤텍스 잠금을 해제한다. 이제 이함수를 관리하는, 즉 뮤텍스 잠금을 관리하는 클래스를 만들어보자. 이런 용도의 클래스는 여태까지 봐온 RAII 법칙을 따라 구성한다. 생성시 -> 자원획득 / 소멸시 -> 자원해제 //뮤텍스 잠금 관리 클래스 class Lock{ pub.. 2019. 12. 30.
항목 13. 자원 관리에는 객체가 그만! 팩토리 메서드를 미리 숙지하고 13장을 살펴보자. 1. 팩토리 패턴 class Investment() { // 투자 관련 최상위 클래스 … }; class InvestmentA : Investment() { //파생클래스 … }; class Creator { public : Investment* Operation() { return factoryMethod(); } protected : virtual Investment* factoryMethod() = 0 ; }; class CreatorA : Creator{ private: Investment* factoryMethod() { return new InvestmentA }; // 투자 파생클래스 객체를 동적할당하고 그 포인터를 반환한다. 따라서 객체의 .. 2019. 12. 19.
항목 12. 객체의 모든 부분을 빠짐없이 복사하자 복사 함수란? 복사함수 = 복사 대입 연산자 + 복사 생성자 항목5에서 확인할 수 있듯이, 객체 복사 함수는 컴파일러에 의해 자동생성된다. 따라서 복사함수를 정의한다는 것은 기본 복사함수가 맘에 안든다는뜻이다. 컴파일러는 이러한 사용자의 행동이 틀려도(구현이 엉망이어도) 입을 닫는다. Class Customer{ private : string name; public : Customer(const Customer& rhs); Customer& operator =(const Customer& rhs); }; 위 예시에서 멤버 변수 age가 추가된다면, 복사함수, 복사생성자에서 age에 대한 복사내용을 추가적으로 구현해야한다. (구현하지 않아도 컴파일러는.. 알려주지않고 정상이라고 말한다..) 또한, 파생클래.. 2019. 12. 18.
항목 11. operator=에서는 자기대입에 대한 처리가 빠지지 않도록 하자 자기대입(Self Assignment)이란, 어떤 객체가 자기 자신에 대해 대입연산자를 적용하는 것을 뜻한다. 자기대입 발생이유? - 중복참조(Aliasing)가 가능하기때문에. 따라서 같은 클래스의 객체를 다룰때는 중복참조를 고려하여 설계해야한다. 1. 예외, 자기대입에 문제가 있는 예시 class Bitmap{ … }; // 동적으로 할당될 Bitmap class Widget { ... private: Bitmap *pb; // 힙에 할당된 객체를 가리키는 포인터 }; //불안정한 '=' 연산자 구현코드 Widget& Widget::operator=(const Widget& rhs) { delete pb; pb = new Bitmap(*rhs.pb); return *this; } 만약 rhs와 *th.. 2019. 12. 18.
항목 10. 대입 연산자는 *this의 참조자를 반환하게 하자 이런 코드를 본 경험이 있을 것이다. int x, y, z; x = y = z = 10; 대입연산자는 right-associative 우측 연관 연산이라는 특성을 가진다. 이는 아래와 같다. x = (y = (z = 10)); 우측 z 부터 순서대로 대입이 진행된다. 보통 이러한 연산자는 참조자를 반환하도록 구현되어 있다. 일종의 관례이다. class Widget { public: … Widget& operator+=(const Widget& rh) { … return *rh; } } "좌변객체의 참조자는 반환하게 만들자"라는 관례는 단순 대입형 연산자 뿐 아니라, +=, -=, *= 등에도 동일하게 적용한다. 굳이 안따라도 컴파일이 안되진 않는다. 하지만 표준 라이브러리 and 기본 타입이 이 관례를 .. 2019. 12. 18.
항목 9. 객체 생성 및 소멸 과정 중에는 절대로 가상 함수를 호출하지 말자 1. 다형성과 가상함수 C++에 다형성을 생각해보자. base 클래스에서 가상함수인 function()를 선언해줬고 derived 클래스에서 가상함수 function()를 오버라이딩해주었다. 이제 메인에서 base b = new derived(); 이후 b.function(); 호출 시 derived의 함수가 호출된다. 이것이 바로 c++의 다형성 특징이다. 근데 만약, base의 생성자에서 가상함수인 function()을 호출하게 되면 "미정의 동작행"으로 빠질 수 있다. 일단 예제 코드를 확인해보자. //기본클래스 class Transaction { public : Transaction(); virtual void logTransaction() const = 0; ... }; Transaction::.. 2019. 12. 17.