본문 바로가기

전체 글

(18)
12. 객체의 모든 부분을 빠짐없이 복사하기 class Customer { ... }; class PriorityCustomer: public Customer { public: ... PriorityCustomer(const PriorityCustomer& rhs): m_Priority(rhs.m_Priority) // rhs의 데이터를 복사한다. { } PriorityCustomer& operator = (const PriorityCustomer& rhs) { // rhs의 데이터를 복사한다. m_Priority = rhs.m_Priority; return *this; } private: int m_Priority; }; PriorityCustomer 파생 클래스는 Customer 기본 클래스의 상속된 데이터까지 가지고 있을 겁니다. 그런데 위에..
11. operator = 자기 대입 처리하기 class Wiget {...}; Wiget w; ... w = w; 위와 같은 소스 코드는 자기 대입이 이루어지고 있는 것을 쉽게 확인할 수 있네요. 그러나 반복문에서 이루어지는 객체의 자기 대입은 언제 놓칠 수도 있기 때문에 일치성 검사, 복사 대입 후 삭제, 복사 후 맞바꾸기 방법을 활용할 수 있습니다. class Bitmap { ... }; class Widget { public: ... private: // 힙에 할당하기 위한 멤버 Bitmap*m_pBitmap; public: // 안전하지 않은 operator = 연산자 Widget& operator = (const Widget& rhs) { // 기존에 할당되어 있는 것을 지운다. delete m_pBitmap; m_pBitmap = new..
10. 대입 연산자는 *this의 참조자를 리턴한다 대입 연산자는 좌변 객체의 참조자를 반환하게 만들자 대입 연산은 우측에서 좌측으로 연쇄적으로 대입된다는 특성이 있습니다. int x, y, z; x = y = z = 15; 이를 보았을 때, 대입 연산이 z = 15, y =15, x = 15 이렇게 사슬같이 연쇄적으로 엮이려면 대입 연산자는 좌변에 대한 참조자를 반환하도록 구현되어 있을 것이라고 예상할 수 있습니다. 그래서 클래스 타입의 대입 연산자를 정의할 때, 이러한 관례를 지키는 것이 좋다고 합니다. class MyFunc { public: ... // 반환 타입은 현재 클래스에 대한 참조자이다. MyFunc& operator = (const MyFunc& rhs) { ... // 좌변 객체(의 참조자)를 반환한다. return *this; } M..
09. 생성자, 소멸자에서 가상 함수를 호출하지 않는다. 기본 클래스 생성자에서 호출한 가상 함수는 파생 클래스쪽으로 내려가지 않는다 // 모든 거래에 대한 기본 클래스 class Transaction { public: Transaction(); // 클래스 타입에 따라 달라지는 거래내역을 로깅하는 함수 virtual void LogTransaction()const = 0; ... }; Transaction::Transaction() { ... // 기본 클래스 생성자의 마지막 동작에서 // 거래내역을 로깅하기 시작한다. LogTransaction(); } // Transaction의 파생 클래스 class BuyTransaction : publicTransaction { public: // 이 클래스 타입(구매 기록)에 따른 거래내역을 로깅한다. virtua..
08. 소멸자와 예외 처리 소멸자에서 예외 처리를 해야 하는 상황 결론부터 봤을 때, 소멸자에서 예외를 던지는 것은 좋지 않다고 합니다. class DBConnection { public: ... static DBConnection create(); // 자신의 객체를 반환. 매개변수 생략 void close(); // 연결을 닫고, 실패하면 예외를 던지는 코드가 있다고 가정 }; // DBConnection 객체를 관리하는 클래스 class DBConn { pubilc: ... ~DBConn() { m_db.close(); // 소멸자를 통해 연결이 항상 닫히도록 한다. } private: class DBConnection m_db; }; { // 블록 시작 DBConn dbc(DBConnection::create()); .....
IOCP (I/O Completion Port) 동기 입출력 호출된 함수가 블로킹 상태로 놓이기 때문에 그 함수가 반환할 때 까지 CPU는 다른 일을 수행할 수 없습니다. 비동기 입출력 입출력 수행시 함수를 호출하자마자 바로 반환합니다. 그래서 CPU는 다른 작업을 할 수 있습니다. Select, WSAEventSelect 멀티플렉싱은 비동기 입출력과 관련이 없는 모델입니다. 비동기 입출력 함수인 WSASend, WSARecv를 활용하는 Overlapped I/O, IOCP가 WinSock의 대표적인 비동기 입출력 모델입니다. Overlapped I/O vs IOCP Winsock 계열로 만들어진 서버 모델의 90퍼센트 이상은 IOCP가 차지하고 있다고 합니다. Overlapped I/O와 IOCP의 차이점 중 하나는 "스레드 풀링"에 있습니다. 스레..
07. 다형성을 가진 기본 클래스 소멸자는 반드시 가상 소멸자로 선언하자 먼저 부모 클래스 소멸자에 virtual이 없는 코드입니다. #include class Base { public: Base() { std::cout
Overlapped I/O Overlapped I/O : 비동기 입출력 하나의 스레드에서 둘 이상의 패킷 데이터를 통신용 소켓에 송수신합니다. 그래서 "여러 개의 소켓에 입출력이 중첩된 상황" 이라고 해서 Overlapped I/O는 중첩된 입출력이라는 뜻으로 보면 될 것 같습니다. 그렇다면 입출력 함수의 입장에서 보았을 때, 즉각적인 반환이 요구됩니다. 이를 가능하게 하려면 입출력 자체를 비동기 방식으로 처리합니다. 이는 윈속에서 OVERLAPPED 구조체와 이에 따른 입출력 함수를 통해 하나 또는 그 이상의 입출력 요청을 한 번에 처리할 수 있습니다. 구조체에 가장 아래에 있는 HANDLE hEvent는 핸들을 저장합니다. 첫번째 ULONG_PTR Internal과 두번째 ULONG_PTR IternalHigh는 운영체제에서 ..