오늘날의 C++은 다중 패러다임 프로그래밍 언어(multiparadigm programming language)라고 불린다.절차적 프로그래밍을 기본으로 객체지향, 함수식, 일반화, 메타 프로그래밍 개념까지 지원한다.이러한 C++을 이해하는 가장 쉽고 정확한 방법은 C
가급적 선행 처리자보다 컴파일러를 더 가까이 하자! 소스코드가 컴파일러에게 넘어가기 전에 선행 처리자가 ASPECTRATIO를 숫자 상수로 바꿨기 때문에, 컴파일러에겐 ASPECTRATIO가 전혀 보이지 않는다. (->컴파일러가 쓰는 기호 테이블에도 없다.) 때문에
const const 객체는 외부 변경이 불가능하게 하며 이를 컴파일러가 보장한다.또한 선행 처리자(\*을 기준으로 const가 오른쪽에 붙으면 포인터가 상수, 왼쪽에 붙으면 포인터가 가리키는 대상이 상수이다.STL iterator는 포인터를 본떠 만들었다. (T\*과
C++의 객체 초기화는 언제 보장되고 언제 보장되지 않은지에 대한 규칙이 명확하다. 예를 들어 배열과 같은 기본 제공 타입(C++의 C)은 초기화된다는 보장이 없으나 vector(C++의 STL)는 초기화를 보장한다. 그러나 이 규칙이 복잡하기 때문에 굳이 외우기보다
사용자가 직접 클래스 안에 선언하지 않아도 컴파일러가 알아서 선언하는 함수에는 기본 생성자, 복사 생성자, 복자 대입 연산자, 소멸자가 있다. 모두 public이자 inline 함수로 선언된다. 즉, 이 Empty 클래스와 이 Empty 클래스는 근본적으로 동일하다
부동산 중개업 소프트웨어에서 집을 나타내는 클래스인 HomeForSale을 선언한다. 그런데 부동산 중개업자가 세상에 똑같은 집은 존재하지 않는다고 신신당부하니 HomeForSale 객체를 복사하려는 코드는 컴파일되지 않도록 하고 싶다. 즉, 다음과 같이 동작하게
소프트웨어에서 시간을 기록해야 하는 일이 종종 발생한다. 따라서 시간 관리를 담당하는 기본 클래스(TimeKeeper)를 만들어 이를 용도에 따라 적절히 파생하여 설계하는 것이 좋다. 사용자는 시간 계산이 어떻게 되는지에 대해서는 궁금하지 않고, 단지 시간 정보에
사용자가 직접 DBConnection 객체에 대해 close를 호출해야 하는 코드이다. 그러나 사용자가 close를 호출하는 것을 잊을 수도 있다. 이를 방지하기 위해 DBConnection에 대한 자원 관리 클래스(DBConn)를 만들고, 그 클래스의 소멸자에서 c
다음은 주식 거래(매도 주문, 매수 주문, ...)를 본떠 만든 클래스들이다. 생성자 아래의 코드가 실행되면 어떤 일이 발생할까? TransAction 생성자가 호출된 뒤 BuyTransaction 생성자가 호출된다. 그런데 위의 코드를 보면, TransAct
C++의 대입연산은 여러 개가 사슬처럼 엮일 수 있다.위의 코드를 풀어쓰면 다음과 같다.15가 z에 대입되고, 그 대입 연산의 결과(갱신된 z)가 y에 대입, 또 그 대입 연산의 결과(갱신된 y)가 x에 대입된다.이렇게 대입 연산이 사슬처럼 엮이는 것은 대입 연산자가
자기대입 어떤 객체가 자기 자신에 대해 대입 연산자를 적용하는 것 언뜻 봐서는 이런 자기 대입 코드를 누가 쓰겠냐 싶지만 많은 사용자들이 이런 코드를 작성하게 된다. ex... 이러한 자기대입이 생기는 이유는 여러 곳에서 하나의 객체를 참조하는 상태인 중복참조(a
객체 복사 함수 복사 생성자 복사 대입 연산자 사용자가 직접 객체 복사 함수를 구현하고 어쩌구 코드 이때 데이터 멤버를 하나 추가하지만 복사 함수는 그대로라면 복사 함수의 동작은 완전 복사가 아니라 부분 복사가 된다.(name은 복사, lastTransaction
서론 프로그래밍에서 자원은 사용을 마치고 나면 시스템에 돌려주어야 하는 모든 것을 말한다. C++ 프로그램에서 자원은 대표적으로 동적 할당한 메모리가 있으며, 이 외에도 file descriptor, mutex lock, GUI 리소스, DB 연결, 네트워크 소켓 등등
힙에서 생기는 자원들은 항목13에서 언급한 uniqueptr, sharedptr과 같은 스마트 포인터로 자원을 관리하면 된다. 그러나 힙이 아닌 공간에서 생성된 자원은 스마트 포인터로 처리하기 적합하지 않다. 이럴 때는 스스로 자원 관리 클래스를 만들어야 한다. 자원
항목 13, 14에서 배운 것을 토대로 자원 관리 객체를 사용한다면, 직접 자원에 접근하지 않으면서 자원 누출에 대한 걱정을 지울 수 있다.그러나 수많은 API들은 자원을 직접 참조하도록 만들어져 있다.결국 자원 관리 객체의 보호를 넘어 실제 자원에 직접 접근해야 할
언뜻 보면 문제 없어 보이는 코드이다. new로 메모리를 할당하고 delete로 해제했기 때문이다. 그러나 이 코드는 미정의 동작으로 빠져버린다. 설령 동작하더라도 stringArray가 가리키는 100개의 string 객체들 중 99개의 객체들은 소멸하지 못할 것
동적 할당한 객체를 스마트 포인터에 저장하기 자원을 관리할 때는 객체를 사용하면 좋으므로(항목 13) processWidget 함수를 동적 할당된 Widget 객체에 대한 스마트 포인터를 사용하도록 만들었다. 컴파일 에러! processWidget 함수를 호출하는
인터페이스 C++에서 함수, 클래스, 템플릿 등이 모두 인터페이스에 해당한다. 인터페이스를 사용했는데 결과 코드가 사용자가 생각한 대로 동작하지 않는다면 애초에 컴파일되지 않아야 한다. 반대로 어떤 코드가 컴파일된다면 사용자가 원하는 대로 동작해야 한다. Date 클
새로운 클래스를 정의한다는 것은 새로운 타입을 정의하는 것과 같다. 우리는 클래스 설계자에 그치지 않고 타입 설계자라는 막강한 권위를 가지고 있다는 것이다. 따라서 클래스를 설계할 때는 마치 언어 설계자가 그 언어의 기본제공 타입을 설계하면서 들인 것과 같은 정성과
C++은 함수로부터 객체를 전달받거나 함수에 객체를 전달할 때 기본적으로 값에 의한 전달(pass by value) 방식을 사용한다. 함수의 매개변수는 실제 인자의 사본을 통해 초기화되며, 어떤 함수를 호출한 쪽은 그 함수가 반환한 값의 사본을 돌려받는다.이 사본은 복
항목 20을 본 후 pass by value를 척살하려는, 모든 코드를 오직 reference to const로만 전달하려는 사람들도 있을 것이다. 이러한 사고방식은 좋지 않다.operator\* 함수가 반환하는 참조자는 이미 존재하는 Rational 객체를 참조한 이
데이터 멤버가 public이 아니어야 하는 이유 1. 문법적 일관성 데이터 멤버가 모두 public이 아니라면, 사용자가 어떤 객체에 접근할 수 있는 유일한 수단은 멤버 함수이다. 다시 말해서 클래스의 공개 인터페이스에 있는 것이 함수뿐이라면, 그 클래스의 멤버에 접근
WebBrowser에 선언한 3가지 함수의 동작을 한 번에 하는 함수 clearEverything을 만들어보자.당연히 멤버 함수가 더 낫다고 생각하겠지만 이러한 경우 비멤버 함수를 채택해야 한다.객체 지향 법칙에 따르면 할 수 있는 만큼 데이터를 캡슐화해야 한다. 그렇
일반적으로 클래스에서 암시적 타입 변환을 지원하지 않는 것이 좋다.그러나 이 규칙에는 예외가 있는데, 가장 흔한 예외는 숫자 타입이다.C++에서 기본으로 제공하는 int->double처럼 정수->유리수 암시적 변환을 허용하기 위해 explicit을 붙이지 않았다.수치연
※ 특수화, 부분 특수화에 대한 이해가 선행되어야 하는 항목이다. >참고 1. 함수 템플릿과 클래스 템플릿 2. C++ 템플릿 특수화/부분 특수화 - 간단 3. C++ 함수 부분 특수화 - 상세 swap 두 객체의 값을 맞바꿈 자기대입 현상(항목 11)의가능성에 대
생성자, 소멸자가 있는 타입의 변수를 정의하면 변수를 정의할 때 생성자, 변수가 유효범위를 벗어날 때 소멸자를 호출하는 비용을 지불한다. 변수가 정의됐으나 사용되지 않더라도 마찬가지encrypted는 예외가 발생한다면 사용하지 않는 변수이다. 그러나 encryptePa
(T) 표현식C 스타일 캐스트 T (표현식)함수 방식 캐스트const_cast<T>(표현식)객체의 상수성을 없애는 용도로 사용dynamic_cast<T>(표현식)안전한 다운캐스팅 연산자주어진 객체가 어떤 클래스 상속 계통에 속한 특정 타입인지 아닌지를 결정하
여기서 upperLeft, lowerRight함수는 상수 함수인데 pData 객체에 대한 참조자를 반환하고 있다.따라서 upperLeft, lowerRight의 리턴값을 통해 Rectangle 객체의 내부 데이터가 수정될 수 있다.클래스 데이터 멤버는 아무리 숨겨도,
예외 안정성의 종류 기본적인 보장 강력한 보장 예외불가 보장 예외를 절대로 던지지 않겠다는 보장으로, 약속한 동작은 언제나 끝까지 완수한다는 의미이다. 참고로 위 함수는 예외불가 보장을 제공하지 않는다. 여기서 throw()는 doSomething에서 지정되지 않
inline 함수 장점 함수처럼 동작하면서, 매크로보다 안전하다. 함수 호출 시 발생하는 오버헤드가 없다. 주의할 점 함수 본문의 길이가 길다면 목적 코드의 크기가 커지며 명령어 캐시 적중률이 떨어진다. 반대로 함수 본문의 길이가 함수 호출문보다 짧다면 목적 코드의
이러한 Person 클래스가 컴파일되기 위해서는 string, Date, Address에 대한 정보를 알아야 한다.때문에 Person.h에는 이러한 include코드가 필요하다.그러나 이 include문으로 인해 Person.h와 위 세 헤더파일간의 컴파일 의존성이 생
Derived 클래스를 Base 클래스로부터 public 상속을 통해 파생시켰다. = Derived 객체는 Base 객체이다. 즉, 상대적으로 Base는 일반적인 개념이며, Derived는 특수한 개념이다. 따라서 Base타입을 쓰는 객체 대신에 Derived객체를
C++의 이름 가리기 규칙에 의하면 안쪽 유효범위에 있는 이름이 바깥쪽 유효범위에 있는 이름을 가린다.컴파일러는 자신이 처리하고 있는 유효범위에서 같은 이름을 가진 것이 있는지 찾는다.cin >> x;에서 x는 지역 변수인 double x 이다. (전역 변수 x의 타입
함수 인터페이스의 상속함수 구현의 상속Shape 클래스는 추상 클래스이므로 파생 클래스만 인스턴스화 가능하다.파생 클래스에게 함수의 인터파이스만을 상속시킨다.모든 Shape 객체는 draw가 가능해야 한다.직사각형과 타원은 각자 그리는 방법이 다르므로 각 클래스에서 직