Object Oriented Programming(C++)60 Effective C++ | 항목 27 캐스팅은 절약, 또 절약! 잊지 말자 항목 27 캐스팅은 최대한 절약하자 27.1 캐스팅 문법 ■ 27.1.1 캐스트 스타일 C 캐스트(구형 스타일 캐스트) (T) 표현식 T (표현식) C++ 캐스트(신형 스타일 캐스트) C++ 캐스트 설명 예시 const_cast(표현식) 객체의 상수성(constness) 혹은 휘발성(volatileness)을 없애는 용도로 사용한다. const → non-const static_cast(표현식) 암시적 변환을 진행하거나 타입을 거꾸로 변환하는 용도로 쓰인다. int → double void* → int* Parent* → Child* reinterpret_cast(표현식) 하부 수준 캐스팅을 위해 만들어진 연산자다. 구현 환경에 의존적이므로 이식성이 없다. int → char* dynamic_cast(표.. 2023. 3. 6. Effective C++ | 항목 26 변수 정의는 늦출 수 있는 데까지 늦추는 근성을 발휘하자 항목 26 변수 정의는 최대한 늦추자 26.1 변수 정의 ■ 26.1.1 변수 정의를 늦추는 방법 어떤 변수를 사용할 때가 되었을 때 비로소 변수를 정의한다. 변수를 정의할 때 초기화 인자로 바로 초기화한다. #include #include using namespace std; const int MinimumPasswordlength = 8; void encrypt(string& s); string encryptPassword(const string& password) { // string encrypted; 예외가 발생할 경우, 이 객체는 사용되지 않습니다. if (password.length() < MinimumPasswordlength) { throw logic_error("pw is too sho.. 2023. 3. 3. 전문가를 위한 C++ | Chapter 11 C++의 까다롭고 유별난 부분(상) 11.1 레퍼런스 C++에서 레퍼런스(reference)란 일종의 변수에 대한 앨리어스(alias), 즉 별칭이다. 변수에 대한 다른 이름이라 생각해도 된다. 11.1.1 레퍼런스 변수 레퍼런스 변수는 반드시 생성하자마자 초기화해야 한다. 예를 들면 다음과 같다. xRef는 x에 대한 또 다른 이름으로 xRef를 사용하는 것은 x를 사용하는 것과 같다. int x = 5; int& xRef = x; int& yRef; /* 컴파일 에러 */ 정수 리터럴처럼 이름 없는 값에 대해서는 레퍼런스를 생성할 수 없다. 단, const 값에 대해서는 레퍼런스를 생성할 수 있다. 임시 객체도 마찬가지로 non-const 레퍼런스는 만들 수 없지만, const 레퍼런스는 얼마든지 만들 수 있다. int& ref1 = .. 2022. 3. 5. Effective C++ | 항목 24 타입 변환이 모든 매개 변수에 적용되어야 한다면 비멤버 함수를 선언하자 항목 24 타입 변환이 모든 매개 변수에 적용되어야 한다면 비멤버 함수를 선언하자 일반적으로 클래스에서 암시적 타입 변환을 지원하는 것은 잘못된 생각이다. 물론 숫자 타입은 예외인데, 예를 들어 정수에서 유리수의 암시적 변환은 허용해도 크게 이상하지 않다. 이 결정에 따라 Rational 클래스를 만들어보자. 24.1 멤버 함수의 암시적 타입 변환 Rational 클래스는 유리수를 나타내는 클래스이므로 덧셈, 곱셈 등 수치 연산을 기본으로 지원하려고 한다. 유리수의 곱셈은 Rational 클래스와 관련이 있으니 operator*를 Rational 클래스 안에 멤버 함수로 구현해보자. class Rational { public: Rational(int numerator = 0, int denominator.. 2022. 2. 15. Effective C++ | 항목 23 멤버 함수보다는 비멤버 비프렌드 함수와 더 가까워지자 항목 23 멤버 함수보다는 비멤버 비프렌드 함수와 더 가까워지자 23.1 멤버 함수 vs. 비멤버 비프렌드 함수 웹 브라우저를 나타내는 클래스가 있다고 가정해보자. 웹 브라우저로 다운로드한 파일을 저장한 캐시를 비우는 함수, 방문한 URL의 기록을 지우는 함수, 시스템이 갖고 있는 쿠키를 삭제하는 함수가 속해있다. 캡슐화 관점에서 봤을 때, 세 동작을 한꺼번에 호출하는 clearBrowserMember 멤버 함수와 clearBrowserNonMember 비멤버 함수 중 누가 더 좋은 걸까? class WebBrowser { public: void clearCache(); void clearHistory(); void clearCookies(); void clearBrowserMember(); }; voi.. 2022. 2. 15. Effective C++ | 항목 22 데이터 멤버가 선언될 곳을 private 영역임을 명심하자 항목 22 데이터 멤버가 선언될 곳은 private 영역임을 명심하자 이번 항목에서는 먼저 데이터 멤버가 왜 public이면 안 되는지 그 이유를 알아보고, 이 이야기가 protected 데이터 멤버에도 똑같이 적용되는 모습을 확인해 보도록 하자. 여기까지 끝나면 데이터 멤버는 반드시 private이어야 한다는 결론을 자연스럽게 볼 수 있을 것이다. 22.1 private가 아닌 데이터 멤버 ■ 22.1.1 public 데이터 멤버 public 데이터 멤버를 먼저 도마 위에 올려보자. 왜 데이터 멤버를 public으로 선언하면 안 될까? ① 문법적 일관성 우선 문법적 일관성에 어긋난다. 데이터 멤버가 private이라면, 사용자 쪽에서 어떤 객체에 접근할 수 있는 유일한 수단은 멤버 함수이므로 그 클래스.. 2022. 2. 11. 전문가를 위한 C++ | Chapter 10 상속 활용하기(하) 10.6 상속에 관련된 미묘하고 흥미로운 문제 10.6.1 오버라이드한 메서드 속성 변경하기 대부분 메서드의 구현을 번경하기 위해 메서드를 오버라이드하지만, 간혹 이 과정에서 원래 메서드의 속성을 변경할 수도 있다. ■ 10.6.1.1 메서드 리턴 타입 변경하기 오버라이드할 메서드는 부모 클래스의 메서드 프로토타입(method prototype) 혹은 메서드 선언과 똑같이 작성하는 것이 원칙이다. 하지만 C++는 부모 클래스의 리턴 타입이 다른 클래스에 대한 포인터나 레퍼런스 타입이면, 메서드를 오버라이드할 때 리턴 타입을 다른 클래스의 자식 클래스에 대한 포인터나 레퍼런스 타입으로 바꿀 수 있다. 이런 타입을 공변 리턴 타입(covariant return type)이라 부른다. 예를 들어, 사과 과수원.. 2022. 2. 10. 전문가를 위한 C++ | Chapter 10 상속 활용하기(중) 10.3 부모를 공경하라 10.3.1 부모 클래스의 생성자 C++는 객체 생성 과정을 다음과 같이 정의하고 있다. 이 규칙은 재귀적으로 적용되어 클래스에 부모 클래스가 있다면 현재 클래스보다 부모 클래스를 먼저 초기화한다. 부모 클래스라면 디폴트 생성자를 실행하거나 생성자 이니셜라이저를 호출한다. non-static 데이터 멤버를 코드에 나타난 순서대로 생성한다. 클래스 생성자의 본문을 실행한다. 부모 클래스에 디폴트 생성자가 있으면 자동으로 호출해주고 디폴트 생성자가 없거나 있더라도 다른 생성자를 사용할 때는 생성자 이니셜라이저로 생성자를 체인으로 엮을 수 있다. CAUTION 자식 클래스에서 부모 클래스의 virtual 메서드를 오버라이드하고 그 메서드를 부모 클래스 생성자에서 호출하면 안 된다. 자.. 2022. 2. 7. Effective C++ | 항목 21 함수에서 객체를 반환할 경우에는 참조자를 반환하려고 하지 말자 항목 21 함수에서 객체를 반환할 경우에는 참조자를 반환하려고 하지 말자 값에 의한 전달에 숨겨진 효율 문제를 알아챈 프로그래머 중에는 코드에 멀쩡하게 들어있는 '값에 의한 전달'을 '참조에 의한 전달'로 모조리 바꾸어 실제로 있지도 않은 객체의 참조자를 넘기는 경우가 있다. 예를 들어, 어떤 유리수를 나타내는 클래스가 있다고 가정해보자. 이 클래스에는 두 유리수를 곱하는 멤버 함수가 선언되어 있다. class Rational { public: Rational(int numerator = 0, int denominator = 1); private: int n, d; /* 분자와 분모를 나타냅니다. */ friend const Rational operator*(const Rational& lhs, cons.. 2022. 2. 3. Effective C++ | 항목 20 값에 의한 전달보다는 상수 객체 참조자에 의한 전달이 대개 낫다 항목 20 값에 의한 전달보다 상수 객체 참조자에 의한 전달이 대개 낫다 20.1 값에 의한 전달: 객체 편 기본적으로 C++는 함수에 객체를 전달하거나 함수로부터 객체를 전달받을 때 값에 의한 전달(pass by value) 방식을 사용한다. 특별히 다른 방식을 지정하지 않는 한, 함수 매개 변수는 실제 인자의 사본을 통해 초기화되고 함수를 호출한 쪽은 그 함수가 반환한 값의 사본을 돌려받는다. 바로 이 사본을 만들어내는 행위 때문에 값에 의한 전달은 고비용의 연산이 된다. 아래 코드를 한번 보자. validateStudent 함수는 Student 인자를 값으로 전달받고 이 인자가 유효한지를 알려주는 bool 값을 반환한다. 이 함수가 호출될 때 과연 어떤 일이 일어날까?class Person {pub.. 2022. 2. 3. Effective C++ | 항목 19 클래스 설계는 타입 설계와 똑같이 취급하자 항목 19 클래스 설계는 타입 설계와 똑같이 취급하자 19.1 클래스 설계 고려사항 C++에서 새로운 클래스를 정의하는 것은 새로운 타입을 정의하는 것과 같다. 그렇기 때문에 클래스를 설계할 때는 마치 기본 타입을 설계하는 것처럼 많은 정성과 노력이 필요하다. 그럼 클래스를 효과적으로 설계하려면 어떤 것들을 고려해야 하는지 우선 파악해보자. 새로운 타입의 객체 생성 및 소멸은 어떻게 이루어져야 하는가? 이 부분에 따라서 클래스 생성자와 소멸자의 설계가 바뀐다. 객체 초기화는 객체 대입과 어떻게 달라야 하는가? (복사) 생성자와 복사 대입 연산자의 동작을 결정하는 요소이다. 초기화와 대입을 헷갈리지 않는 것이 중요하다. 새로운 타입으로 만든 객체가 값에 의해 전달되는 경우, 어떤 의미를 부여할 것인가? 어.. 2022. 2. 3. Effective C++ | 항목 18 인터페이스 설계는 제대로 쓰기엔 쉽게, 엉터리로 쓰기엔 어렵게 하자 2022. 2. 3. 이전 1 2 3 4 5 다음