More Programmings/Effective C++

최상위 클래스를 만들고 난 후 에 이를 파생한 클랙스 객체를 사용하는 경우에는 팩토리 함수를 사용해야 한다.ex)class Investment{...}; //클래스 형태의 최상위 클래스Investment* createInvestment(); //Investment class를 클래스 객체로 동적 할당 후 그 포인터 반환delete createInvestment; //객체를 해제 객체 해제시 중간에 return 문이 들어가있는 경우 문제가 발생할 수 있음.따라서 이는 자원이 누수될 수 있는 문제를 방생 시킬수 있음.해결방법1. auto_ptr: 포인터와 비슷하게 동작하는 객체(스마트 포인터), 가리키고 있는 대상에 대해 소멸자가 자동으로 delete를 불러주도록 설계사용 방법 void f() { std::..
객체를 복사할 때 기존 클래스 내부에 있는 함수까지 모든 부분을 복사를 해주어야 한다.클래스가 상속한 기본 클래스의 복사함수, 해당 클래스의 데이터의 모든 부분을 복사해야 한다. *중요 사항- 객체 복사함수는 주어진 객체의 모든 데이터 및 모든 기본 클래스 부분을 빠뜨리지 말고 복사해야 한다.- 클래스의 복사 함수를 두 개 고현할 때 한쪽을 이용해서 다른 한쪽을 구현하려고 하면 안된다.
자기대입(self assignment): 어떤 객체가 자기 자신에 대해 대입 연산자를 적용하는 것을 말함*px = *py;라는 구문의 경우 가리키는 대상이 같으면 자기 대입이 된다.(중복 참조) 자기 참조의 가능성이 높은 코드 예시 Widget& Widget::operator=(const Widget& rhs) //안전하지 않게 구현된 operator= { delete pb; //현재의 비트맵 사용을 중지 pb = new Bitmap(*rhs.pb); //rhs의 비트맵을 사용하도록 만듬 return *this; } *문제 되는 상황- operator= 내부에서 *this와 rhs가 같은 객체일 가능성이 있기 때문에 이를 검사해줄 필요가 있음. *해결방법1. 일치성 검사(identity test) Wid..
int x, y, z; x = y = z = 15; //대입이 사슬처럼 이어짐 좌변 인자의 좌변 객체를 반환하게 만들어야 한다. class Widget { public: Widget& operator+=(const Widget& rhs) { return this; } Widget& operator\(int rhs) //대입 연산자의 매개변수 타입이 일반적이지 않은 경우에도 동일한 규약을 적용한다. { return *this; } }; * 중요사항- 대입 연산자는 반드시 *this의 참조자를 반환하도록 하게 한다.
가상 함수는 파생 클래스 쪽으로 내려가지 않는다.(본 클래스에서 처리를 해야한다)기본 클래스 생성자는 파생 클래스 생성자보다 앞서서 실행되기 때문에 기본 클래스 생성자가 돌아가고 있는 경우 파생 클래스 생성자는 아직 초기화가 되지 않음. class Transaction { public: Transaction() { init();} // 비가상 멤버 함수를 호출하고 있다. virtual void logTransaction() const = 0; private: void init() { logTransaction(); //이 비가상 함수에서 가상 함수를 호출하고 있다. } };*위 코드는 문제가 있는 코드 *정상 코드 class Transaction { public: explcit Transaction(co..
class의 소멸자에 예외를 발생하는 코드를 추가하는 경우 문제가 발생할 수 있다.문제상황 class DBConn { public: ... ~DBConn() { db.close(); } private: DBConnection db; }; db연결이 바로 닫히지 않거나 이미 닫혀 있는 경우 문제를 발생시킨다. 해결 방법 /* 프로그램을 바로 끝냄 */ DBConn::~DBConn () { try{db.close(); } catch (...) { 호출 실패 로그 std::abort(); } } /* 예외를 삼켜 버림 */ DBConn: ~DBConn () { try { db.close(); } catch(...) { 호출 실패 로그 } } *중요사항- 소멸자에서는 예외가 빠져나가면 안됨- 어떤 클래스의 연산..
class TimeKeeper { public: TimeKeeper(); ~TimeKeeper(); }; class AtomicClock: public TimeKeepeer {}; class WaterClock: public TimeKeeper {}; class WristWatch: public TimeKeeper {}; 시간 접근자에 접근을 하려고 함 TimeKeeper* getTimeKeeper(); //TimeKeeper에서 파생된 클래스를 통해 동적으로 할당된 객체의 포인터를 반환 기본 클래스의 소멸자로 인해 클래스가 삭제가 되면 파생 클래스는 소멸되기 때문에 객체의 신세로 바뀌게 된다. 따라서 에러가 발생될 수 있음 이를 해결하기 위해서는 virtual을 포함하여 가상 소멸자를 만들면 이를 해결..
HomeForSale h1; HomeForSale h2; HomeForSale h3(h1); //h1을 봉사하려 합니다 컴파일 되면 안된다 h1 = h2; // h2를 복사하려 합ㄴ다 컴파일 되면 안된다 class Uncopyable { protected: // 파생된 객체에 대해서 Uncopyable() {} //생성과 소멸을 ~Uncopyable() {} //허용합니다 private: Uncoptable(const Uncopyable&); // 하지만 복사는 방지합니다. Uncopyable& operator = { const Uncopyable&); }; class HomeForeSale: private Uncopyable { // 복사 생성자도, ... //복사 대입 연산자도 }; //이제는 선언되..
클래스가 비어 있지만 비어 있지 않은 경우가 존재한다. c++에서 빈 클래스를 지나갈 때가 이런 경우 중에 하나 이다. 클래스 안에 직접 선언하지 않더라도 선언되는 것 1. 복사 생성자 2. 복사 대입 연산자 3. 소멸자 class Empty { public: Empty() {... } //기본 생성자 Empty(const Empty& hrs) { } //복사 생성자 ~Empty() { } //소멸자 Empty& operator=(const Empty&rhs){ } // 복사 대입 연산자 }
int x; 초기화를 하지 않으면 이 x의 값이 어떤 값인지 알 수 없다 stl의 벡터 부분의 경우 반드시 초기화가 보장이 된다 int x = 0; //int의 직접 초기화 const char * text = "A C-style string"; //포인터의 직접 초기화 double d; //입력 스트림에서 읽음으로써 초기화 수행 class PhoneNumber{...}; class ABEntry { //ABEntry = "Address Book Entry" public: ABEntry(const std::string&name, const std::string& address, const std::list& phones); private: std::string theName; std::string theA..
플로쨔응
'More Programmings/Effective C++' 카테고리의 글 목록