Books
[Effective C++] 9. 객체 생성 및 소멸 과정 중에는 절대로 가상 함수를 호출하지 말자
[Effective C++] 9. 객체 생성 및 소멸 과정 중에는 절대로 가상 함수를 호출하지 말자
2022.05.14먼저 이 단원에서 얘기하고 싶은 내용을 얘기하자면 객체 생성 및 소멸 과정에서 가상 함수를 호출하면 "미정의 동작"을 할 수 있기 때문에 호출하면 안 된다는 것이다. 이런 현상이 발생하는 원인에 관해서 알아보자. 다형성과 가상 함수 base클래스에서 가상 함수 function()을 선언하고, derived클래스에서 가상 함수 function을 오버라이딩 해준 구조를 생각해보자. 이제 메인에서 base b = new drived(); 이후 b.function(); 호출 시 derived의 함수가 호출되는데, 이게 바로 C++의 다형성의 특징이다. 근데 base의 생성자에서 가상 함수인 function을 호출하게 되면 어떻게 될까? 일단 예제를 확인해보자. class Transaction { public: ..
[Effective C++] 8. 예외가 소멸자를 떠나지 못하도록 붙들어 놓자
[Effective C++] 8. 예외가 소멸자를 떠나지 못하도록 붙들어 놓자
2022.05.14제목의 의미는 소멸자에서 예외가 빠져나오지 않도록 처리하자는 것을 의미한다. 소멸자가 호출되는 경우 정상적으로 객체가 종료되었을 때 예외처리 메커니즘에 의해 객체가 소멸될 때 위에서 예외처리 메커니즘에 의해 객체가 소멸될 때 또 예외가 발생한다면, terminate함수가 호출되어 프로그램이 종료된다. 따라서 try~catch로 예외를 소멸자 내에 묶어 두어야 한다. 아래의 코드를 보면, class DBConnection { public: static DBConnection create(); // DB 생성 void close(); // 연결 닫기 } ---- class DBConn { public: ~DBConn() { db.close(); // DB 연결 닫기 } private: DBConnection..
[Effective C++] 7. 다형성을 가진 기본 클래스에서는 소멸자를 반드시 가상 소멸자로 선언하자
[Effective C++] 7. 다형성을 가진 기본 클래스에서는 소멸자를 반드시 가상 소멸자로 선언하자
2022.05.13C++의 다형성을 통해 우리는 공통 기능을 가진 하나의 클래스를 기본 클래스로 만들고 적절한 용도에 따라 파생시켜 사용할 수 있으므로, 이렇게 파생시킨 객체를 쉽게 사용하기 위해 이 객체에 대한 포인터를 가져오는 용도로 팩토리 함수를 사용하면 좋을 것 같다. 그럼 팩토리 함수부터 알아보자. 팩토리 함수 새로 생성된 파생 클래스 객체에 대한 기본 클래스 포인터를 반환하는 함수로 파생 클래스의 객체를 new로 할당하기 때문에 메모리를 적절히 삭제해야 한다. 하지만 잘 못 사용하면 문제가 될 수 있는데, 아래의 예시를 보고 문제가 되는 부분을 찾아보자. class TimeKeeper { public: TimeKeeper(); ~TimeKeeper(); } class AtomicClock: public Time..
[Effective C++] 6. 컴파일러가 만들어낸 함수가 필요 없으면 확실히 이들의 사용을 금해 버리자
[Effective C++] 6. 컴파일러가 만들어낸 함수가 필요 없으면 확실히 이들의 사용을 금해 버리자
2022.05.09복사 생성자와 복사 대입 연산자를 사용하고 싶지 않을 때 항목 5에서 컴파일러가 은근슬쩍 만들어내는 함수들에 대해 알았으니, 이러한 함수들을 사용하고 싶지 않을 때에 대해서 알아보자. 첫 번째 해결의 열쇠는 다음과 같다. 컴파일러가 생성하는 함수들은 모두 public멤버가 되지만, 직접 선언할 때는 public멤버로 선언해야 한다고 요구하는 부분은 없다는 점이다. 즉, 복사 생성자 및 복사 대입 연산자를 private 멤버로 선언하면 클래스 멤버 함수가 명시적으로 선언되기 때문에 컴파일러는 자신의 기본 버전을 만들 수 없음 private의 접근성을 가지므로 외부로부터 호출도 불가능하여 복사를 할 수 없음 두 가지 이유로 인해 외부에서 복사는 불가능하게 할 수 있다. 하지만 private멤버 함수는 그 클..
[Effective C++] 5. C++가 은근슬쩍 만들어 호출해 버리는 함수들에 촉각을 세우자
[Effective C++] 5. C++가 은근슬쩍 만들어 호출해 버리는 함수들에 촉각을 세우자
2022.05.08비어있지만, 비어있지 않은 class C++에서는 직접 선언하지 않아도 복사 생성자(copy constructor), 복사 대입 연산자(copy assignment operator), 소멸자(destructor), 생성자를 기본형으로 선언해준다. 이들은 모두 public멤버이며 inline 함수이다. 즉, 아래의 클래스를 선언했더라도 class Empty {}; 생성자와 소멸자, 복사 생성자, 복사 대입 연산자들이 암시적으로 선언되어 있는 것과 같다. class Empty { public: Empty() {...} // 기본 생성자 Empty(const Empty& rhs) {...} // 복사 생성자 ~Empty() {...} // 소멸자 Empty& operator=(const Empty& rhs) ..
[Effective C++] 4. 객체를 사용하기 전에 반드시 그 객체를 초기화하자
[Effective C++] 4. 객체를 사용하기 전에 반드시 그 객체를 초기화하자
2022.05.07C++의 초기화 C++은 객체의 값의 초기화를 보장하지 않는다. 초기화되지 않은 값을 내버려 두면 정의되지 않은 동작이 그대로 나올 수 있기 때문에 항상 초기화를 해주는 것이 좋다. 기본 제공 타입으로 만들어진 비멤버 객체에 대해서 초기화는 아래처럼 할 수 있으며 int x = 0; // int의 직접 초기화 const char * text = "A C-style string"; // 포인터의 직접 초기화 double d; std::cin>> d; // 입력 스트림에서 읽음으로써 초기화 수행 이런 부분을 제외한 C++의 초기화 나머지 부분은 생성자로 귀결되기 때문에 생성자에서 지킬 규칙은 간단하다. 그 객체의 모든 것을 초기화하면 된다. 이때, 대입(assignment)을 초기화(initializatio..
[Effective C++] 3. 낌새만 보이면 const를 들이대 보자!
[Effective C++] 3. 낌새만 보이면 const를 들이대 보자!
2022.05.07const의 매력 '의미적인 제약'을 소스코드 수준에서 붙인다는 점 컴파일러가 이 제약을 단단히 지켜준다는 점 즉, 어떤 값이 불변이어야 한다는 제작자의 의도를 컴파일러 및 다른 프로그래머와 나눌 수 있는 수단이 된다는 점이 매력적이라 볼 수 있다. const는 팔방미인 클래스 바깥에서 전역 혹은 네임스페이스 유효 범위의 상수를 선언(정의)하는 데 사용할 수 있으며 파일, 함수, 블록 유효 범위에서 static으로 선언 한 객체에도 const를 붙일 수 있다. 클래스 내부에서는 정적 멤버 및 비정적 데이터 멤버 모두를 상수로 선언할 수 있다. Q. 포인터는 어떨까? char greeting[] = "Hello"; char* p = greeting; // 비상수 포인터, 비상수 데이터 const char*..
[Effective C++] 2. #define을 쓰려거든 const, enum, inline을 떠올리자
[Effective C++] 2. #define을 쓰려거든 const, enum, inline을 떠올리자
2022.05.06주제에 더 가까운 제목은 가급적 선행 처리자보다 컴파일러를 더 가까이 하자.라고 한다. #define 상수의 단점 #define ASPECT_RATIO 1.653 ASPECT_RATIO가 기호식 이름으로 보이지만 컴파일러에게 넘어가기 전에 전처리기가 숫자 상수(1.653)로 바꿔버리기 때문에 ASPECT_RATIO라는 이름은 컴파일러가 쓰는 기호 테이블에 들어가지 않는다. 그래서 숫자 상수로 대체된 코드에서 컴파일 에러라도 발생하게 되면 에러 찾기가 꽤나 힘들 수 있다. (소스코드엔 ASPECT_RATIO, 에러 메시지는 1.653) 또, 기호 테이블에 이름이 없기 때문에 기호식 디버거에서도 문제가 나타날 수 있다. 해결 방법 : const const double AspectRatio = 1.653; 상..
[Effective C++] 1. C++을 언어들의 연합체로 바라보는 안목은 필수
[Effective C++] 1. C++을 언어들의 연합체로 바라보는 안목은 필수
2022.05.04초창기의 C++ 단순히 C 언어에 객체 지향 기능 몇 가지가 결합된 형태 오늘날의 C++ 다중패러다임 프로그래밍 언어(multiparadigm programming language)로 아래의 개념들을 지원하고 있다. 절차적 프로그래밍 객체 지향 프로그래밍 함수식 프로그래밍 일반화 프로그래밍 메타 프로그래밍 따라서 C++을 잘 사용하기 위해선 단일 언어가 아닌, 상관관계가 있는 여러 언어들의 연합체로 봐야 한다. C++의 하위 언어 C++은 4가지의 하위 언어들로 이루어져 있다. 1. C C++의 기본이 되는 언어 블록, 문장, 선행 처리자, 기본 제공 데이터 타입, 배열, 포인터 등 2. 객체 지향 개념의 C++ '클래스를 쓰는 C'에 관한 모든 것 클래스(생성자와 소멸자 개념까지), 캡슐화, 상속, 다..