728x90

26. 변수 정의는 늦출 수 있는 데 까지 늦추는 근성을 발휘하자. 

   - 생성자 혹은 소멸자를 끌고 다니는 타입 변수를 정의하면 물게 되는 비용이 2가지 있는데, 하나는 제어 흐름이 변수의 정의에 

     닿을 때 생성자가 호출되는 비용과 그 변수가 유효 범위를 벗어날 때 소멸자가 호출되는 비용이다. 변수가 사용이 끝나고 소멸

     이 되기 전에 예외를 발생하거나 하는 상황이 발생하게 되면 소멸자를 호출하지 못하고 끝나게 되는 상황을 상당히 자주 볼 수 

     있게 된다. 최대한 늦출 수 있도록 하는 것이 프로그램을 좀 더 효율적으로 구동시킬 수 있으며, 변수가 근처에 있기 때문에 확

     인하기도 편하다. 

 

27. 캐스팅은 절약, 또 절약! 잊지 말자.

   - "어떤 일이 있어도 타입 에러가 생기지 않도록 보장한다"는 C++의 바탕이 되는 철학이다. 이 말은 즉 이론적으로 C++는 컴파일

     만 되면 그 이후에는 어떤 객체에 대해서도 불안전한 연산이나 말도안되는 연산을 수행하려 들지 않는다는 것이다. 이 철학을 

     깨는 것이 캐스팅인데 캐스팅은 총 3개의 방법이 있다.

     (T) 표현식    // 표현식 부분을 T타입으로 캐스팅

     T (표현식)    // 표현식 부분을 T타입으로 캐스팅

     의 구형 스타일 캐스팅과 신형 스타일 캐스팅이 있다.

     신형 스타일 캐스팅은 static_cast, dynamic_cast등 총 4개지가 있다.

     가능하다면 캐스팅을 피하도록 다른 방법을 시도한 뒤 더 이상 캐스팅 이외의 방법이 없을 때만 사

     용하자. 캐스팅을 쓰려거든 구형 캐스팅을 사용하지말고, C++스타일의 신형 캐스팅을 사용하자.

     (발견하기 쉽고 어떤 의도로 사용하는지 파악가능)

 

28. 내부에서 사용하는 객체에 대한 핸들을 반환하는 코드는 되도록 피하자.

   - 객체에 내부 요소에 대한 핸들(참조자, 포인터, 반복자)를 반환하게 되면, 객체에 상수성을 가지고 있는 요소에 대해 유지가 불

     가능 하게 될 뿐만 아니라 캡슐화 정도를 낮추는 원인되 된다. 또한 무효 참조 핸들이 생기는 경우도 생길 수 있으니 되도록 피

     하자.

 

29. 예외 안전성이 확보되는 그날 까지.

   - 함수를 설계할 때 항상 예외 안전성을 고려하도록 하자. 예외 안전성을 가진 함수라면 예외가 발생할 때 자원이 새도록 만들지 

     않으며, 자료구조가 더럽혀지는 것을 허용하지 않게 된다.

     또한 3가지의 보장중 하나를 제공하는데 기본적인 보장(basic guarantee), 강력한 보장(strong quarantee), 예외불가 보장

     (nothrow guarantee)가 있다.

 

30. 인라인 함수는 모두 이해하도록 하자.

   - 인라인 함수는 함수처럼 보이고 함수처럼 동작하며, 매크로보다 훨씬 안전하고 쓰기 좋다. 또한 인라인 함수는 명령이 아닌 컴

     파일러에 요청을 하는 것이다. 즉 컴파일러가 암시적으로 할 수도 있다.

     대표적인 예가 클래스 정의 안에 함수를 바로 넣을 때 해당 함수를 인라인 후보로 찍는 경우이다.

     또한 조건이 갖추어져 있더라도 인라인이 되지 않는 경우도 있는데 함수의 주소를 취하는 코드를 사용할 때 이다. 대표적인 예

     가 생성자, 소멸자이다. 인라인은 작고, 자주 호출되는 함수에 대해서만 하는 것으로 묶는 것이 좋다. 디버깅 및 라이브러리 바

     이너리 업그레이드가 용이 해지고 코드 부풀림 현상이 최소화 되며, 조금 더 프로그램 속도가 빨라지게 된다.

 

31. 파일 사이의 컴파일 의존성을 최대한 줄이기(전방 선언)

   - 컴파일 의존성을 최소화하는 작업의 배경이 되는 가장 기본적인 아이디어는 '정의'대신에 '선언'에 의존하게 만들자는 것이다. 

     이 아이디어에 기반한 두 가지 접근 방법은 핸들 클래스와 인터페이스 클래스이다. 라이브러리 헤더는 그 자체로 모든 것을 갖

     추어야 하며 선어부만 갖고 있는 형태여야 한다. 이 규칙은 템플릿이 쓰거나 쓰이지 않거나 동일하게 적용하도록 노력하자.

 

32. public 상속 모형은 반드시 "is a"를 따르도록 하자.

   - 기본 클래스에 적용되는 모든 것들이 파생 클래스에 그대로 적용되어야 한다.

     모든 파생클래스 객체는 기본 클래스 객체의 일종이기 때문이다.

     Person클래스와 이를 상속한 Student클래스가 있을 때 "사람은 학생일 수도 있지만 학생이라고 해서 반드시 사람은 아니다"라

     는 개념으로 접근해보자.

 

33. 상속된 이름을 숨기는 일은 피하자.

   - 파생 클래스의 이름은 기본 클래스의 이름을 가리케 된다. public 상속에서 이런 이름 가림현상은 바람직하지 못하다. 가려진 

     이름을 다시 볼 수 있게 하는 방법은 using 선언 혹은 전달 함수를 사용할 수 있다.

     void foo_Student()

     {

          Person::foo();

     }

 

34. 인터페이스 상속과 구현 상속의 차이를 제대로 파악하고 구별하자.

   - 순수 가상 함수는 인터페이스 상속만을 허용하며, 단순 가상함수는 인터페이스 상속과 더불어 기본 구현의 상속도 가능하도록 

     지정할 수 있다. 비가상함수는 인터페이스 상속과 더불어 필수 구현의 상속도 가하도록 만들자.

 

35. 가상 함수 대신 쓸 것들도 생각해두는 자세를 시시 때때로 길러두자.

   - 가상 함수를 함수 포인터 데이터 멤버로 대체한다.

   - 한쪽 클래스 계통에 속해 있는 가상 함수를 다른 쪽 계통에 속해있는 가상 함수로 대체한다.

   - 가상 함수 대신에 쓸 수 있는 방법으로 NVI관용구 및 전략 패턴 (Non Virtual Interface)가 있다.

   - 객체에 필요한 기능을 멤버 함수로부터 클래스 외부의 비멤버함수로 옮기면, 그 비멤버 함수는 그클래스의 public 멤버가 아닌 

     것들을 접근할 수 없다는 단점이 생긴다.

   - tr1::function 객체는 일반화된 함수 포인터처럼 동작하는데 이 객체는 주어진 대상 시그너처와 호환되는 모든 함수 호출성 개체

     를 지원한다.

 

36. 상속 받은 비가상함수를 파생 클래스에서 재정의하는 것은 절대 금물.

   - 비가상함수는 정적바인딩(프로그램 소스에 스인 각종 내부요소, 이름, 식별자 등에 대해 빌드 중에 값 혹은 속성을 확정하는 과

     정)으로 묶이고 가상 함수는 동적 바인딩(실행중에 확정)으로 이루어져 있기 때문이다.

 

     바인딩 : int foo = 2;가 있을 대 데이터 타입은 int인 것과 변수명이 foo로 정해지는 것은 정적 바인딩, 변수에 2가 대입되는 것

     이 동적 바인딩이다. C++에서는 컴파일 중 아예 가상 함수 테이블을 파생 클래스에 맞게 바꿈으로서 겉보기에는 파생 클래스 타

     입에서 오버라이드한 가상 함수를 호출 하는 것 처럼 보이게 만든다.

 

37. 어떤 함수에 대해서도 상속 받은 기본 매개변수 값은 절대로 재정의 하지 말자.

   - 기본 매개 변수 값은 정적 바인딩에 비해 가상 함수는 동적으로 바인딩 되기 때문이다.

 

38. has -a 혹은 is-implement-interms-of를 모형화할 때는 객체 합성을 사용하자.

   - 포함된 객체들을 모아서 이들을 포함한 다른 객체를 합성한다는 뜻으로

     class Person

     {

          string name;

          Address address;

          Data data;

     };

     등과 같은 경우이다.

 

     여기서 선지식으로 소프트웨어 개발에서 영역이라는 부분이 있다.

     이 부분 중 사람, 이동수단, 비디오 프레임 등 일상 생활에서 볼 수 있는 사물을 본 뜬 객체는 응용 영역(Application Domain)

     에 속하는데 여기서 객체 합성이 응용 영역의 객체들 사이에서 일어나면 has -a의 관게이고 구현 영역에서 일어나면 

     is implement in terms of의 관계를 나타낸다.

 

39. private 상속은 심사숙고해서 구사하자.

   - private 상속에는 두가지 동작 규칙이 있는데 첫번재는 일반적으로 파생클래스 객체를 기본 클래스 객체로 변환하지 않는 것과 

     기본 클래스로부터 물려바든 멤버는 모두 private 멤버로 바뀐다는 것이다. 여기서 private 상속은 is imlement in terms of의 의

     미를 가지고 있는데 어떤 클래스를 파생시킨 것은 부모 클래스에서 쓸 수 있는 기능들 몇개를 활용할 목적으로 한 행동이지, 부

     모와 자식클래스의 객체들 사이에 어떤 개념적 관계가 있어서 한 행동이 아니라는 것, 즉 private 상속 자체가 구현 기법 중 하나

     라는 것이다. 섣불리 이 방식을 쓸 필요가 없다는 생각을 갖고 모든 대안을 고민해보고 주어진 상황에서 두 클래스 사이의 관계

     를 나타낼 가장 좋은 방법이 private 상속이라는 결론이 나면 쓰는 것이 좋다.

 

40. 다중 상속은 심사 숙고해서 구사하자.

   - 다인 상속보다 복잡할 뿐만 아니라 새로운 모호성 문제를 일으킬 수 이싸. 가상 상속이 필요해지는 경우가 있다.

     예) 부모가 둘 이상이고 부모의 부모 클래스가 데이터 멤버를 가질 경우 가장 하위 클래스에게는 2개의 데이터 멤버가 생기는 결

         과가 나온다 이럴 때 가상 상속을 사용해야 한다.

   - 가상 상속을 사용하면 크기 비용, 속도 비용이 늘어나며, 초기화 및 대입 연산의 복잡도가 상당히 커진다. 가상 기본 클래스에

     는 데이터를 두지 않는 것이 현실적이다.

   - 적합한 경우는 여러 시나리오 중 하나가 인터페이스 클래스로부터 public 상속을 시킴과 동시에 구현을 돕는 클래스로부터 

      private 상속을 시키는 것이다.

 

출처 : http://blog.naver.com/sorkelf/40146367692

728x90

+ Recent posts