목록C++ (43)
방프리
항목 29 : 예외 안전성이 확보되는 그날 위해 싸우고 또 싸우자! 코딩을 할 때 가장 염두해야할 것 중 하나를 고르자면 예외처리가 빠질 수 없습니다. 필자도 동물에 비유하면서까지 예외처리의 중요성을 설명할 정도이니깐요. 예외 안전성을 가진 함수면 예외가 발생시 다음과 같이 동작해야 합니다. 1) 자원이 새도록 만들지 않습니다. 2) 자료구조가 더럽혀지는 것을 허용하지 않습니다. 예외 안전성을 가진 함수는 아래의 세 가지 보장 중 하나를 제공하여 줍니다. 1) 기본적인 보장(basic guarantee) : 함수 동작 중에 예외가 발생하면, 실행 중인 프로그램에 관련된 모든 것들을 유효한 상태로 유지하겠다는 보장입니다. 하지만 사용자측에서는 예측할 수 없습니다. 2) 강력한 보장(string guaran..
항목 28 : 내부에서 사용하는 객체에 대한 '핸들'을 반환하는 코드는 되도록 피하자 이 항목에 대해 알아보기 전 '핸들'에 대해 먼저 짚고 가는 것이 좋을 것 같습니다. 핸들이란? 다른 객체에 접근할 수 있게 해주는 매개자를 말합니다. 간단하게 get, set 함수를 예를 들 수 있겠네요 get, set 함수는 캡슐화의 규약을 지키면서 데이터를 조작, 접근을 가능하게 해줍니다. 하지만 get, set 함수를 가지고 있는 클래스를 멤버변수로 가지고 있는 클래스에서도 데이터 조작이 가능해집니다. 즉, 캡슐화를 위해 만든 함수가 다른 방법을 통해 조작이 이루어진다는거죠 private 또는 protected로 선언된 변수들은 보호받을 권리가 있습니다. 이들 변수 외에도 포인터와 같은 핸들을 반환하는 코드로 된..
항목 27 : 캐스팅은 절약, 또 절약! 잊지 말자 - 필자는 캐스팅 스타일에 따라 다음과 같이 분류했습니다. (1) (DataType)expression // 표현식 부분을 DataType으로 캐스팅 합니다. (2) DataType(expression) // 표현식 부분을 DataType으로 캐스팅 합니다. (1)의 경우 C 문법 스타일의 캐스팅 방법이고, (2)의 경우 함수호출문과 비슷한 캐스팅 방법입니다. 두 방법은 서로 작성방식이 다르지만 결과값은 같습니다. 이 두가지 방식을 통틀어서 '구형 스타일의 캐스트'라고 합니다. C++의 경우엔 새로운 4가지의 캐스트 연산자를 독자적으로 제공합니다. const_cast : 객체 상수성을 없애는 용도로 사용됩니다. dynamic_cast : 안전한 다운캐스..
항목 26 : 변수 정의는 늦출 수 있는 데까지 늦추는 근성을 발휘하자 - 하나의 변수를 호출하면 반드시 그 변수를 위한 생성자와 소멸자가 호출되기 마련입니다. 가끔 코딩을 하다보면 반드시 사용하진 않더라도 필요한 변수들을 볼 수 있습니다. 가령 일정 길이 이상의 비밀번호에 대해서만 암호화를 진행하는 코드를 짠다고 한다면 이렇게 작성하는 분들도 계실 것 입니다. std::string encryptPassword(const std::string& password) { using namespace std; string encrypted; //비밀번호가 길 때를 대비해 암호화 변수를 만듭니다. if( password.length() < MinimumPasswordLength ) { throw logic_err..
항목 25 : 예외를 던지지 않는 swap에 대한 지원도 생각해보자 - swap은 개발자들도 다들 알다싶히 값을 서로 교환하는 알고리즘을 말합니다. 딱히 알고리즘이라고 말하기도 뭐한... 그런 함수이죠 가장 기초적인 함수가 왜 이 항목에서 등장할까요? 필자는 STL에 이 함수가 포함된 이래, 예외 안전성 프로그래밍에선 없어선 안될 감초 역활로써, 자기 대입 현상의 가능성에 대처하기 위한 대표적인 매커니즘으로서 널리 사랑받아왔다고 설명합니다. 그러면서 이 swap 함수를 사용하면서 비용을 복사라는 비용을 지불하게 되는데 이 항목에서 그 비용을 지불하지 않는 방법을 설명해줍니다. 바로 다른 타입의 실제 데이터를 가리키는 포인터가 주성분인 타입의 객체(pimpl)을 소개해주는데요. 이런 객체 전용의 함수를 제..
항목 24 : 타입 변환이 모든 매개변수에 대해 적용되어야 한다면 비멤버 함수를 선언하자. - 클래스를 생성하고 그 클래스에 대한 연산자를 오버라이딩할 때 항상 멤버 함수를 오버라이딩을 해왔습니다. 그로인해 이러한 연산 코드도 가능했죠. ex) class Point { private: int x, y; public : Point(); ~Point(); const Point operator*(const Point& arg); }; 하지만 이 함수가 모든 곳에 적용이 되진 않습니다. 가령 ex) Point p1, p2; p2 = 2 * p1; // 에러 발생! 이러한 코드가 있다면 Point 클래스의 재정의 된 *이 아닌 상수 2의 * 연산자가 되어버리기 때문입니다. 즉, 곱셈의 주체가 클래스 객체가 아니라..
항목 23 : 멤버 함수보다는 비멤버 비프렌드 함수와 더 가까워지자 -객체지향적으로 생각한다면 멤버 함수는 가장 뛰어난 함수입니다. 관련 클래스의 데이터를 기반으로 동작하기도 하고, 관련 클래스에 묶여있기 때문입니다. 하지만 이는 잘못된 정보라고 필자는 말합니다. 멤버 함수의 남용은 객체지향의 기본 3대 요소 중 하나인 캡슐화를 해칠 가능성이 매우 크다고 합니다. 또한 비멤버 함수를 사용하면 패키징 유연성이 높아지는 장점도 가질 수 있습니다. 한마디로 멤버 함수가 적으면 적을 수록 해당 클래스의 멤버 변수에 접근하는 빈도가 점점 줄어든다는 뜻입니다. 비프렌드 함수도 마찬가지 입니다. 프렌드 함수를 사용하게 되면 해당 클래스의 멤버 변수를 private로 선언하더라도 접근이 가능해지기 때문에 캡슐화의 의도..
항목 22 : 데이터 멤버가 선언될 곳은 private 영역임을 명심하자! C++에서 클래스를 배울 때 초반에 배우는 것으로 접근지정자( 접근 한정자라고도 합니다.)를 배우게 됩니다. 즉, 멤버변수 혹은 멤버함수에 접근할 수 있는 객체를 제한하는 것이죠. 총 3가지 키워드가 있으며 각각 private, protected, public이 있습니다. 이 부분에서 데이터 멤버(멤버변수)가 public이 되면 안되는 이유를 먼저 살펴보겠습니다. (1) 문법적 일관성 유지 유지보수 기간이 길어질 수록 코드의 양은 반드시 늘어납니다. 양이 많아질 수록 문제되는 것이 사람이 코딩하는 것이기 때문에실수할 확률이 커지지요. 이 실수를 줄이는 방법은 굉장히 다양한데 문법적 일관성도 그 중 하나입니다. 멤버변수, 멤버함수 ..