SlideShare ist ein Scribd-Unternehmen logo
1 von 52
Effective C++ 정리
Chap5~6
131054 이인재
항목 26 : 변수 정의는 늦출 수 있
는 데까지 늦추자
• 생성자 혹은 소멸자를 끌고 다
니는 타입으로 변수를 정의하
면 반드시 생성자 호출, 소멸
자 호출을 하는데 들어가는 비
용이 생긴다.
• 변수가 정의되었는데 상요되
지 않을 경우에도 쓸데없는 비
용이 생긴다.
• ->사용될 줄 알고 생성한 변수
가 사용이 안되는 경우가 생길
수 있다.
• 언뜻 보면 encrypted가 반드시 사용되는 변수인 것
같지만 if 문에서 걸리면 사용되지 않는 변수가 된
다.
변수 정의는 꼭 필요해질 때 하자
• 조건에 걸려버리면 encrypted
는 쓸모없는 변수가 되어버리
므로, 꼭 필요해지기 전까지
encrypted의 정의는 미루는 것
이 좋다. • encrypted가 사용 될 수 있는 시점에 와야 비로소
변수로서 의미를 가지므로 다음과 같이 선언하면
변수 낭비의 비용이 발생하지 않는다.
• 주의할 점은 루프안에서의 문제인데 이때는
A : 루프 바깥족에 정의 -> 생성자 1 + 소멸자 1 +
대입 n
B : 루프 안쪽에서 정의 ->생성자 n + 소멸자 n
두 방법의 효율을 따져서 정한다.
정의와 동시와 초기화를 하는게
좋다
• 초기화 인자를 손에 넣기 전까
지 정의를 늦출 수 있는지 보
아야 한다.
-> 대입연산자를 이용하면 초
기화를 이용하는 것보다 비용
이 더 들어가기 때문에, 정의
와 동시에 초기화를 하면 기본
생성자 호출의 낭비를 막을 수
있다.
• 루프안에서는 일반적으로는
루프 바깥족에서의 정의하는
것이 효율이 좋다(대입에 들어
가는 비용이 생성자-소멸자 쌍
보다 더 적을 경우가 많다)
항목 26 정리
• 변수 정의는 늦출 수 있는 때까지 늦추자
• 초기화 인자가 나올때까지, 객체 정의를 늦추자
• 루프안에서의 변수 정의는 케이스 바이 케이스
로 효율을 따져서 결정하자
항목 27 : 캐스팅은 절약, 또 절약
• 캐스트에 항상 주의해야 한다.
• C스타일의 캐스트, C++스타
일의 캐스트 중 C++ 스타일의
캐스트를 쓰는 것이 더 좋다
-> 어떤 것인지 알아보기 쉽고
, 캐스트의 사용목적을 좀더
명확하게 알아 볼 수 있다.
• c스타일의 캐스트와, c++스타일의 static_cast를 통
해 double 타입의 a를 int타입으로 강제 형변환 시
켜준 예시
C와 C++에서의 캐스팅
문법
• 될 수 있으면 C++ 의 캐스팅 방법을 쓰는 것이
좋다!
실수하기 쉬운 캐스팅
• 가상 함수를 파생 클래스에서
재정의해서 구현할 때 기본 클
래스의 버전을 호출을 먼저 할
때
-> static_cast를 이용한 this
객체는 임시객체이므로 의도
한대로 함수호출이 되지 않는
다.
다운캐스팅 시 주의
• 폭포식 dynamic_cast를 쓰지 말 것!
다운 캐스팅 없이 파생된 클
래스타입의 컨테이너를 이
용
다운 캐스팅 없이 가상함수
집합으로 기본 클래스에 넣
어두기
항목 27 정리
• 되도록이면 캐스팅을 피하자
• dynamic_cast는 정말 신중하게 쓰자.
• 캐스팅이 반드시 필요하다면 함수 안에 숨길수
있도록 하자
• C 스타일보다 C++ 스타일의 캐스트를 쓰도록 하
자
항목 28 : 내부에서 사용하는 객
체에 대한 ‘핸들’을 반환하는 코드
는 피하자• 클래스 멤버 데이터는 그 멤버
의 참조자를 반환하는 함수들
의 접근도에 따라 캡슐화가 정
해진다.
• 참조자 뿐만 아니라 핸들(참조
자, 포인터, 반복자 처럼 다른
객체에 손을 댈 수 있게 하는
매개자)을 반환하게 만들면 캡
슐화가 보장되지 않는다.
• 특히 private로 외부 공개가 금
지된 데이터에 대해서 핸들을
반환할 시 그 캡슐화가 깨질
수 있기때문에 주의해야 한다.
• 핸들을 반환하는 코드는 사용하면 안된다.
반환타입에 const를 붙이면 수정
불가하게 만들 수 있다
• const키워드를 붙임으로써 오직 읽도록만 할 수
있다.
항목 28 정리
• 어떤 객체의 내부요소에 대한 핸들( 참조자, 포인
터, 반복자)를 반환하는 것은 피하자
• 무효참조 핸들이 생기는 경우를 최소화 하자.
• 캡슐화 정도를 높이기 위해서 핸들 반환하는 것
을 피하자
항목 29 : 예외 안전성이 확
보되도록 하자• 강력한 보장 : 함수 동작 중에 예외가 발생하면,
프로그램의 상태를 절대로 변경하지 않겠다는
보장. 이런 함수를 호출하는 것은 원자적인 동작
이라 한다.
• 예외불가 보장 : 예외를 절대로 던지지 않겠다는
보장. 약속한 동작은 언제나 끝까지 완수하는 함
수
• 기본적인 보장 : 함수 동작 중에 예외가 발생하면
, 실행 중인 프로그램에 관련된 모든 것들을 유요
한 상태로 유지. 어떤 객체나 자료구조도 더럽히
지 않으며, 일관성을 유지하게 한다.
항목 29 정리
• 예외 안전성을 갖춘 함수는 실행 중 예외가 발생되
더라도 자원을 누출시키지 않는다.
• 예외 안전성 보장은 기본적인 보장, 강력한 보장,
예외 금지 보장이 있다.
• 강력한 예외 안전성 보장은 ‘복사-후-맞바꾸기’ 방
법을 써서 구현, 모든 함수에 대해 실용적인 것은
아니다.
• 어떤 함수가 제공하는 예외 안전성 보장의 강도는
그 함수가 내부적으로 호출하는 함수들이 제공하
는 가장 약한 보장을 넘지 않는다.
항목 30 : 인라인 함수는 잘 따져
서 이해하자• 인라인 함수는 함수 호출문을 그
함수의 본문으로 바꿔치기
• 함수 호출 비용이 면제
• 메모리가 제한된 프로그램에서
는 코드가 커져서 문제가 발생할
수 있음
• inline은 컴파일러에 대해 ‘요청’
이지 ‘명령’이 아님
• 암시적인 인라인 방법은 클래스
정의 안에 함수를 바로 구현(정
의)
• 명시적인 방법에는 함수 정의 앞
에 inline키워드를 붙임
• GetAge멤버함수는 클래스 정의 내부에서 구현되
어있고, 이것은 곧 암시적인 인라인 요청을 하는 것
임을 뜻한다.
• Max함수라는 것은 명시적으로 inline키워드를 써서
인라인함수 요청을 컴파일러에게 했다.
C++에서의 인라인 함수
• 대부분의 C++ 프로그램에서 함수 인라인은 컴파일 타임에 진행
• 인라인이 끌고 오는 비용은 바로 코드 비대화
• 대부분의 컴파일러의 경우 아무리 인라인 함수로 선언(요청)을 했다 하더
라도, 컴파일러 자신이 보기에 복잡하거나 인라인에 적합하지 않다면 절
대로 인라인의 대상에 넣지 않음
• 가상함수는 절대로 인라인 해주지 않음
->virtual의 의미는 어떤 함수를 호출할지 결정하는 작업을 실행중에 한다
는 것인데 인라인은 그 위치에 호출된 함수를 끼워넣는 작업이다. 컴파일
러는 실행전에 그 위치에 함수의 코드를 끼워 넣어야 되는데 그 함수가 어
떤건지 알 수 없다.
• 생성자와 소멸자는 인라인하기에 좋지않다.
->동적으로 만들었다면 생성자에서 초기화 해주거나, 상속을 받았다면 기
본 클래스의 생성자를 호출해 준다든가, 멤버 데이터들을 초기화해준다거
나 하는 일들을 한다. 이런것들을 전부 인라인으로 처리해 버리면 호출되
는 함수들이 전부 코드로 들어가버리므로 똑같은 함수들을 여러개 가지는
꼴이 되어버릴 수 있다.
항목 30 정리
• 함수 인라인은 작고, 자주 호출되는 함수에 대해
서만 하자
-> 디버깅 및 라이브러리의 업그레이드가 용이,
프로그램의 속도가 빨라질 가능성이 있음
• 되도록이면 아무것도 인라인하지말고( 컴파일러
가 알아서 인라인으로 적합한 것은 인라인으로
바꾸어줌), 인라인해야하는 경우는 정말 단순한
함수에 한해서만 해줌
항목 31 : 파일 사이의 컴파일 의
존성을 최대로 줄이자
• 어떤 것이 컴파일 되려면 그것
에 속한 정보들이 있어야 하는
데 이때 쓰이는 지시자가
#include이다.
• #include는 파일과 헤더파일
들 사이에 컴파일 의존성을 엮
어버린다. 즉 이것에 엮여 있
는 모든 것들이 이것에 의존하
게 되는 것이다.
• 의존성이 높아져버리면 컴파
일이 꼬리에 꼬리를 물어 굉장
한 성능저하를 가져올 수 있다
.
• 위의코드만 가지고 Person클래스가 컴파일 되지
않는다. Person의 구현의 한 부분인 string, Date,
Address등 연관된 것들의 정보가 있어야 컴파일 된
다. 이때 쓰는 것이 #include 지시자이다. 즉
#include “date.h”, #include “address.h”, #include
<string> 선언되어야 한다.
인터페이스와 구현을 둘로 나누
자• 정의부에 대한 의존성을 선언
부에 대한 의존성으로 바꿈
-> 컴파일 의존성을 최소화하
는 원리
• 객체 참조자 및 포인터로 충분
한 경우 객체를 직접 쓰지 않
는다.
• 할 수 있으면 클래스 정의 대
신 클래스 선언에 최대한 의존
하도록 한다.
->클래스를 사용하는 함수를
선언할 때는 그 클래스의 정의
는 굳이 가져오지 않아도 된다
.
• 선언부와 정의부에 대해 별도
의 헤더파일 제공
• 어떤 클래스를 사용하는 함수를 선언할 때는 그 정
의는 필요 없음
• 또는 이렇게 헤더파일을 만드는데 선언만 되어있는
헤더파일만으로도 가능
항목 31 정리
• 컴파일 의존성을 최소화하자
• 컴파일 의존성을 최소화하는 아이디어
-> ‘정의’ 대신에 ‘선언’에 의존하게 만들자
• 라이브러리 헤더는 그 자체로 모든 것을 가줓어
야 하며 선언부만 갖고 있는 형태여야 한다.
항목 32 : public상속은 is-a관계
• public 상속은 “is-a”를 의미한
다
• Cat클래스를 Animal 클래스로
부터 상속을 통해 파생시켰다
면 이 뜻은 ‘Cat 타입으로 만들
어진 모든 객체는 Animal타입
의 객체이지만 그 반대는 성립
하지 않는다’ 이다
• Animal객체가 쓰일 수 있는 모
든 곳에는 Cat객체도 쓰일 수
있다고 단정하는 것
• cat is a Animal 이 되지만 반대인 Animal is cat은
말이 안된다.
항목 32 : public상속은 is-a관계
• Bird 객체인 a는 수영을 할 수
없다.
• Penguin 객체인 b는 수영을
할 수 있다.
• Penguin객체인 b는 날 수 없
지만 Bird에 기본 함수는 날 수
있다고 되어있기에, 가상함수
를 이용하여 재정의
-> 인간의 언어 때문에 클래스
설계에 있어 오류를 범하는 경
우가 많이 있다. 설계시 주의
해야 하는 사항
항목 31 정리
• public 상속의 의미는 “is-a” 관계이다. 기본 클래
스에 적용되는 모든 것들이 파생 클래스에도 그
대로 적용이 된다.
-> 이는 파생 클래스 객체도 기본객체의 일종으
로 보기 때문이다.
항목 33 : 상속된 이름을 숨기는
일을 피하자
• C++ 컴파일러는 유효범위 안
에서 어떤 변수의 이름을 만나
면 일단 자신이 처리하는 유효
범위를 뒤져서 같은 이름이 있
는지 확인.
• 그 유효범위에 있으면 더이상
탐색하지 않음
• 그 유효범위에 없다면 다음 영
역의 유효범위를 탐색
• 컴파일러는 자신이 처리하고있는 곳의 유효범위부
터 탐색해 나간다.
클래스에서의 이름 가리기
• 파생 클래스 Dervied 의 mf1은
Base의 mf1(int)를 가린다.
• 파생 클래스 Dervied 의 mf3
는 Base의 mf3(), mf3(double)
을 가린다.
-> 이러한 이유는 파생클래스
에서 멀리 떨어져 있는 기본
클래스의 오버로드 버전을 상
속하는 것을 ‘실수’로 간주하
겠다는 컴파일러의 의도 때문
이다.
• Derived클래스의 mf1, mf3로 인해 오버로드 된
Base 클래스의 mf1, mf3또한 가려지게 된다.
using 키워드 이용
• 파생 클래스에 의해 가려진 기
본 클래스의 오버로드된 함수
들은 using 키워드를 통해 끄
집어낼 수 있다.
• 즉, 오버로드된 함수들 중에
재정의를 하고 싶은것이 있다
면 파생클래스에서 재정의를
하고, using 키워드를 붙여주
면 된다.
• using 키워드를 통하여 기본클래스의 mf1, mf3의
이름이 derived영역에서도 유효하게 되었다
항목 33 정리
• 파생 클래스의 이름은 기본 클래스의 이름을 가
린다
• public 상속에서의 이런 이름 가림 현상은 바람직
하지 않다
• 가려진 이름을 다시 볼 수 있게 하는 방법으로
using 선언 혹은 전달 함수를 쓸 수 있다.
항목 34 : 인터페이스 상속과 구
현상속의 차이 알기
• pubilc상속의 개념은 함수 인
터페이스의 상속과 더불의 함
수 구현의 상속
• 인터페이스 -> 함수의 선언
구현 -> 함수의 정의
• public으로 상속을 받았다는 것은 기본적으로 인터
페이스 + 구현 까지 상속을 받은 것이다. Derived
는 Base를 public으로 상속받으므로 Base의 인터
페이스 및 구현을 상속 받은 것.
순수가상 함수는 인터페이스 상
속을 뜻한다
• 순수 가상 함수를 상속받는 파
생 클래스에서는 그 가상함수
를 다시 선언해야 한다.
• 순수 가상 함수는 전형적으로
추상 클래스 안에서는 정의를
갖지 않는다.
• 순수 가상 함수를 선언하는 목
적은 파생 클래스에게 함수의
인터페이스만을 물려주는 것. • 부모 클래스인 Shape에서 Draw는 순수 가상 함수
로 선언. 즉 파생클래스인 Triangle에서 다시 선언
및 구현을 해주어야 한다.
비순수가상 함수는 인터페이스 상속
과 더불어 그 함수의 기본적 구현을
물려받게 함
• 비순수 가상 함수는 인터페이
스와 더불어 기본적 구현을 물
려받게 하는 방법
• 파생 클래스에서 따로 재정의
하지 않아도 된다
->기본적 구현을 물려받았기
때문에
• 파생클래스에서 따로 재정의
해도 된다
-> 가상함수로 인터페이스 상
속과 더불어 구체적인 구현도
가능하기 때문에
• 기본 클래스의 Error은 비순수가상 함수로 이에대
한 인터페이스와 기본적인 구현을 물려받음
비가상 함수는 인터페이스와 필
수적인 구현까지 물려받음
• 비가상 함수를 선언하는 목적
은 파생 클래스가 함수 인터페
이스와 더불어 그 함수의 필수
적인 구현을 물려받게 하는 것
• 비가상 함수는 클래스 파생에
관계없이 동작에 있어 변하는
것이 없을 때 사용
• 즉, 파생클래스에서 재정의 하
는 것이 아니다.
• SetName과 GetShapeName함수는 비가상 함수인
데, 파생클래스라 하더라도 이름을 정하고 받아오
는 함수는 동작에 변화가 없으므로 비가상 함수로
선언.
항목 34 정리
• 인터페이스 상속은 구현상속과 다르다
• public상속은 기본 클래스의 인터페이스를 모두
물려 받는다
• 순수 가상 함수는 인터페이스만 상속
• 비순수 가상 함수는 인터페이스 상속과 더불어
기본 구현의 상속도 가능
• 비가상 함수는 인터페이스 상속과 더불어 필수
구현의 상속
항목 35 : 가상 함수 대신 쓸 것들
도 생각해두자
• 비가상 인터페이스 관용구를 사용하자 : 공개되
지 않은 가상 함수를 비가상 public멤버 함수로
감싸서 호출
• 가상 함수를 함수 포인터 데이터 멤버로 대체하
자
• 가상 함수를 tr1::function 데이터 멤버로 대체하
여 호환되는 시그너처를 가진 함수호출성 개체
를 사용할 수 있도록 하자
• 한쪽 클래스 계통에 속해 있는 가상 함수를 다른
쪽 계통에 속해 있는 가상 함수로 대체하자
항목 35 정리
• 가상 함수 대신에 쓸 수 있는 다른 방법으로 NVI
관용구 및 전략 패턴을 들 수 있다 이중 NVI 관용
구는 그 자체가 템플릿 메서드 패턴의 한 예시
• 객체에 필요한 기능을 멤버 함수로부터 클래스
외부의 비멤버 함수로 옮기면, 그 비멤버 함수는
그 클래스의 public 멤버가 아닌 것들을 접근할
수 없다는 단점이 생김
• tr1::function 객체는 일반화된 함수 포인터처럼
동작. 이 객체는 주어진 대상 시그너처와 호환되
는 모든 함수호출성 개체 지원
항목 36 : 상속받은 비가상 함수를
파생 클래스에서 재정의하는 것은
절대 금물• 비가상 함수는 정적 바인딩
-> 빌드 중에 이름, 식별자, 값, 속
성들의 내부요소를 정의.
• 가상 함수는 동적 바인딩
-> 실행중에 이름, 식별자, 값, 속성
들의 내부요소를 정의.
• 자기 자신의 객체가 아닌 객체를
가리키는 포인터 타입에 의해 어떤
함수를 호출할 지 결정.
• 비가상 함수를 public으로 상속받
으면 인터페이스와 필수 구현을 그
대로 물려받음 -> 파생클래스에서
재정의하는 것은 모순(Triange is a
Shape이 성립하지 않음)
• Shape클래스에서 비가상 함수를 구현하고 이를
Triangle클래스가 상속을 받았는데, 다시 그 비가상
함수를 재정의 하고 있다. 해당 객체 자신( Triangle
객체 a ) 이 아닌 그것을 가리키는 포인터 pT에 의
해 좌우된다.
항목 36 정리
• 상속받은 비가상 함수를 재정의하는 일은 절대
로 하면 안된다.
• public상속 관계의 “is- a” 관계에 모순이 생김
• 재정의 할 필요가 있는 함수라면 가상 함수로 정
의하는 것이 맞다.
항목 37: 어떤 함수에 대해서도 상속
받은 기본 매개변수 값은 절대로 재정
의하지말자
• 비가상 함수는 정적 바인딩
-> 빌드 중에 이름, 식별자, 값,
속성들의 내부요소를 정의.
• 가상 함수는 동적 바인딩
-> 실행중에 이름, 식별자, 값,
속성들의 내부요소를 정의.
• 기본 매개변수는 정적 바인딩
• Triangle의 객체를 생성해서 Triangle의 func() 를
실행하면 size = 1이 되어 나온다. 즉, Triangle클래
스에서 매개변수를 재정의한 것이 의미가 없다는
것이다.(매개변수는 기본 클래스 것을 이용) -> 꼬
여버림
비가상 인터페이스를 이용하여
해결
• 파생 클래스에서 재정의할 수
있는 가상 함수를 private 멤버
로 둔다.
• 이 가상 함수를 호출하는
public비가상 함수를 기본 클
래스에 만든다.
• 비가상 함수가 기본 매개변수
를 지정할 수 있게 한다.
• func를 비가상함수로 만들고, 재정의할 수 있는 함
수 Dofunc를 만들어 호출. 비가상 함수가 기본 매개
변수를 지정하도록 할 수 있음.
항목 37 정리
• 상속받은 기본 매개변수 값은 절대로 재정의하
면 안된다.
• 기본 매개변수는 정적으로 바인딩
• 가상함수는 동적으로 바인딩
• 함수호출이 꼬여버리는 경우가 생길 수 있다.
항목 38: “has-a”혹은 “is-implemented-in-
terms-of”를 모형화할 때는 객체 합성을
사용
• 합성이란 어떤 타립의 객체들
이 그와 다른 타입의 객체들을
포함하고 있을 경우에 성립하
는 그 타입들 사이의 관계
• 합성 대신에 레이어링, 포함,
통합, 내장 등으로도 쓴다.
• …has a~ : …은 ~를 가진다
• …is-implemented-in-terms-
of~ : …은 ~를 써서 구현된다.
• Person 객체는 이름, 주소, 핸드폰전화번호 등을
가지고 있는 객체이므로, Person과 string
m_Name, Address m_Address, PhoneNumber
m_celPhone 은 “has - a “ 관계.
• Person has a name;
• Person has a Address;
과
• public 으로 상속을 받는다면
이는 is-a관계이다.
• STL의 set 클래스를 만드는데
list STL을 이용하고자 한다.
• 이때 set 은
set is-implemented-in-terms-
of list가 되는 것이고 이 두 관
계가 되는 것이다.
• 위의 관계로 is-a로 해석해버리면 set is a list가 되
어야 하는데 list 는 중복을 허용하지만 set은 그렇
지 않다. 즉 성립하지 않음을 알 수 있다.
• 밑의 관계로 is-implemented-in-terms-of가 되면 set
은 list를 이용하여 만들어졌다 로 자연스럽게 해석
할 수 있다.
항목 38 정리
• 객체 합성의 의미는 public 상속이 가진 의미와
완전히 다르다
• 응용 영역에서 객체 합성의 의미는 has-a 이다
• 구현 영역에서 객체 합성의 의미는 is-
implemented-in-terms-of이다.
항목 39: private 상속은 심사숙고
해서 구사하자
• private 상속은 분명히 is-a를
뜻하지 않는다.
• private로 상속 받으면 컴파일
러는 일반적으로 파생 클래스
객체를 기본 클래스 객체로 변
환하지 않는다.
• 기본 클래스로부터 물려받은
멤버는 파생 클래스에서 모조
리 private멤버가 된다.
• private상속의 의미는 is-
implemented-in-terms-of, 인터
페이스는 물려받지 못하고 구
현만 물려받을 수 있다.
• S는 더이상 Person으로 간주되지 않는다. 다만 S
는 Person의 몇 가지 특성을 사용한다는 뜻이다.
객체 합성과 private상속의 차이
• 객체 합성도 is-implemented-
in-terms-of의 관계를 갖는다.
• 되도록이면 객체 합성을 사용
하고, 꼭 필요한 경우에만
private사용
-> 꼭 필요한 경우라 하면 비
공개 멤버를 접근할 때 혹은
가상 함수를 재정의할 경우.
• 어떤 클래스에서 필요한 기능
이 있는데 이것을 public상속
을 받는다면 is-a 관계가 되어
모순이 일어난다. 따라서 이렇
게 어떤 기능을 이용할 때에는
private 상속을 받을 수 밖에
없다.
• private상속은 public상속과 객체합성을 이용하여
피할 수 있다. 하지만 관계는 더 복잡해진다.
항목 39 정리
• private상속의 의미는 is-implemented-in-terms-
of이다
• 파생 클래스 쪽에서 기본 클래스의 protected 멤
버에 접근해야 할 경우, 상속받은 가상 함수를 재
정의해야 할 경우에 private 상속을 고려해보아
야 함
• 객체 합성과 달리, private 상속은 공백 기본 클래
스 최적화(EBO)를 활성화시킬 수 있다.
항목 40: 다중 상속은 심사숙고해
서 사용하자
• 다중 상속은 단일 상속보다 구
조가 복잡
• 다중 상속하면 둘 이상의 기본
클래스로부터 똑같은 이름( 멤
버 함수, 멤버 변수 등 )을 물
려받을 가능성이 생긴다.
• Son 객체인 me는 Father 와 Mother의 다중 상속을
받고 있고, 다시 Father 와 Mother 는 Person으로
부터 단일 상속을 받는다. 이때 Son 객체의 Do()를
호출 하면 Father의 것인지 Mother의 것인지 알 수
없기에 에러가 발생한다.
모호성을 없애기 위해 호출할 기
본 클래스의 함수를 손수 지정• 모호성을 없애기 위해 호출할
기본 클래스를 지정해주어야
한다.
• 만약 데이터멤버의 중복생성
을 원한 것이 아니었다면 데이
터 멤버를 가진 클래스를 가상
기본 클래스로 만들어야 한다.
-> 기본 클래스가 상속되는 경
로 갯수만큼 데이터가 중복생
성 되는 걸 막기 위해서
• 가상 상속을 사용하는 클래스
는 가상 상속을 쓰지 않는 클
래스보다 크기가 크고, 속도도
느리다
-> 가상 상속은 비싸다
• me.Father::Do()로 호출할 기본 클래스를 지정해줌
으로써 어떤 함수를 호출할 지 컴파일러가 알게되
어, 호출이 된다.
가상 상속
• 가상 상속을 하지 않으면 Fater와
Mater 클래스를 다중상속 받는
Son객체가 생성 될 때
1. Father와 Mother 의 부모인
Person클래스가 각각 생성
2. Father와 Mother를 상속받음
• 만약 자식에서 Person의 허용된
데이터 및 함수를 읽고자 할 때,
Father의 것인지, Mother의 것인지
알 수 없어서 모호함 -> 에러
• virtual 로 상속 받으면 Father와
Mother의 부모인 Person을 한 번
만 생성 -> 조상이 Person하나이
므로 Person의 허용된 데이터 및
함수 사용 가능
• 가상상속을 통하여 조상의 함수를 바로 호출 가능
항목 40 정리
• 다중 상속은 단일 상속보다 확실히 복잡하다
• 모호성이 생길 여지가 있다
• 가상 상속이 필요해질 때가 있는데, 가상 상속을
사용하면 크기, 속도 면에서 비가상 상속과 비교
하여 좋지 않다
• 가상 상속 시 가상 기본 클래스에는 데이터를 두
지 않는 것이 좋다 -> 초기화 및 대입 연산의 복
잡도가 커지기 때문에

Weitere ähnliche Inhalte

Was ist angesagt?

Effective c++ 3
Effective c++ 3Effective c++ 3
Effective c++ 3현찬 양
 
Effective c++chapter8
Effective c++chapter8Effective c++chapter8
Effective c++chapter8성연 김
 
Effective c++ 정리 chapter 6
Effective c++ 정리 chapter 6Effective c++ 정리 chapter 6
Effective c++ 정리 chapter 6연우 김
 
Effective c++chapter3
Effective c++chapter3Effective c++chapter3
Effective c++chapter3성연 김
 
Effective c++ 4
Effective c++ 4Effective c++ 4
Effective c++ 4현찬 양
 
이펙티브 C++ (7~9)
이펙티브 C++ (7~9)이펙티브 C++ (7~9)
이펙티브 C++ (7~9)익성 조
 
effective c++ chapter 3~4 정리
effective c++ chapter 3~4 정리effective c++ chapter 3~4 정리
effective c++ chapter 3~4 정리Injae Lee
 
How to use the Ruby programing language
How to use the Ruby programing languageHow to use the Ruby programing language
How to use the Ruby programing languageJaeYeoul Ahn
 
Effective C++ Chaper 1
Effective C++ Chaper 1Effective C++ Chaper 1
Effective C++ Chaper 1연우 김
 
Multithread programming 20151206_서진택
Multithread programming 20151206_서진택Multithread programming 20151206_서진택
Multithread programming 20151206_서진택JinTaek Seo
 
More effective c++ chapter1 2_dcshin
More effective c++ chapter1 2_dcshinMore effective c++ chapter1 2_dcshin
More effective c++ chapter1 2_dcshinDong Chan Shin
 
이펙티브 C++ 스터디
이펙티브 C++ 스터디이펙티브 C++ 스터디
이펙티브 C++ 스터디quxn6
 
More effective c++ 항목30부터
More effective c++ 항목30부터More effective c++ 항목30부터
More effective c++ 항목30부터Dong Chan Shin
 
Effective c++ 2
Effective c++ 2Effective c++ 2
Effective c++ 2현찬 양
 
Effective c++ 1
Effective c++ 1Effective c++ 1
Effective c++ 1현찬 양
 
Effective c++ 챕터 2 정리
Effective c++ 챕터 2 정리Effective c++ 챕터 2 정리
Effective c++ 챕터 2 정리연우 김
 
Mec++ chapter3,4
Mec++ chapter3,4Mec++ chapter3,4
Mec++ chapter3,4문익 장
 
Effective c++ Chapter6
Effective c++ Chapter6Effective c++ Chapter6
Effective c++ Chapter6세빈 정
 
Effective c++ 1~8장
Effective c++ 1~8장 Effective c++ 1~8장
Effective c++ 1~8장 Shin heemin
 
Effective c++ 정리 1~2
Effective c++ 정리 1~2Effective c++ 정리 1~2
Effective c++ 정리 1~2Injae Lee
 

Was ist angesagt? (20)

Effective c++ 3
Effective c++ 3Effective c++ 3
Effective c++ 3
 
Effective c++chapter8
Effective c++chapter8Effective c++chapter8
Effective c++chapter8
 
Effective c++ 정리 chapter 6
Effective c++ 정리 chapter 6Effective c++ 정리 chapter 6
Effective c++ 정리 chapter 6
 
Effective c++chapter3
Effective c++chapter3Effective c++chapter3
Effective c++chapter3
 
Effective c++ 4
Effective c++ 4Effective c++ 4
Effective c++ 4
 
이펙티브 C++ (7~9)
이펙티브 C++ (7~9)이펙티브 C++ (7~9)
이펙티브 C++ (7~9)
 
effective c++ chapter 3~4 정리
effective c++ chapter 3~4 정리effective c++ chapter 3~4 정리
effective c++ chapter 3~4 정리
 
How to use the Ruby programing language
How to use the Ruby programing languageHow to use the Ruby programing language
How to use the Ruby programing language
 
Effective C++ Chaper 1
Effective C++ Chaper 1Effective C++ Chaper 1
Effective C++ Chaper 1
 
Multithread programming 20151206_서진택
Multithread programming 20151206_서진택Multithread programming 20151206_서진택
Multithread programming 20151206_서진택
 
More effective c++ chapter1 2_dcshin
More effective c++ chapter1 2_dcshinMore effective c++ chapter1 2_dcshin
More effective c++ chapter1 2_dcshin
 
이펙티브 C++ 스터디
이펙티브 C++ 스터디이펙티브 C++ 스터디
이펙티브 C++ 스터디
 
More effective c++ 항목30부터
More effective c++ 항목30부터More effective c++ 항목30부터
More effective c++ 항목30부터
 
Effective c++ 2
Effective c++ 2Effective c++ 2
Effective c++ 2
 
Effective c++ 1
Effective c++ 1Effective c++ 1
Effective c++ 1
 
Effective c++ 챕터 2 정리
Effective c++ 챕터 2 정리Effective c++ 챕터 2 정리
Effective c++ 챕터 2 정리
 
Mec++ chapter3,4
Mec++ chapter3,4Mec++ chapter3,4
Mec++ chapter3,4
 
Effective c++ Chapter6
Effective c++ Chapter6Effective c++ Chapter6
Effective c++ Chapter6
 
Effective c++ 1~8장
Effective c++ 1~8장 Effective c++ 1~8장
Effective c++ 1~8장
 
Effective c++ 정리 1~2
Effective c++ 정리 1~2Effective c++ 정리 1~2
Effective c++ 정리 1~2
 

Ähnlich wie Chapter5 ~ 6

이펙티브 C++ 5,6 장 스터디
이펙티브 C++ 5,6 장 스터디이펙티브 C++ 5,6 장 스터디
이펙티브 C++ 5,6 장 스터디quxn6
 
Effective cpp
Effective cppEffective cpp
Effective cppTonyCms
 
Effective c++ chapter 1,2 요약
Effective c++ chapter 1,2 요약Effective c++ chapter 1,2 요약
Effective c++ chapter 1,2 요약Nam Hyeonuk
 
Effective C++ Chapter 1 Summary
Effective C++ Chapter 1 SummaryEffective C++ Chapter 1 Summary
Effective C++ Chapter 1 SummarySeungYeonChoi10
 
Effective c++ 정리 chapter 4
Effective c++ 정리 chapter 4Effective c++ 정리 chapter 4
Effective c++ 정리 chapter 4연우 김
 
More Effective C++ 4주차
More Effective C++ 4주차More Effective C++ 4주차
More Effective C++ 4주차Injae Lee
 
Effective c++ chapter 7,8
Effective c++ chapter 7,8Effective c++ chapter 7,8
Effective c++ chapter 7,8문익 장
 
The c++ programming language 10장 클래스 발표
The c++ programming language 10장 클래스 발표The c++ programming language 10장 클래스 발표
The c++ programming language 10장 클래스 발표재정 이
 
연산자 오버로딩
연산자 오버로딩연산자 오버로딩
연산자 오버로딩수빈 박
 
Effective java
Effective javaEffective java
Effective javaHaeil Yi
 
[아꿈사] The C++ Programming Language 13장 템플릿
[아꿈사] The C++ Programming Language 13장 템플릿[아꿈사] The C++ Programming Language 13장 템플릿
[아꿈사] The C++ Programming Language 13장 템플릿해강
 
Cpp에서 활용해보는 Lambda식
Cpp에서 활용해보는 Lambda식Cpp에서 활용해보는 Lambda식
Cpp에서 활용해보는 Lambda식TonyCms
 
Effective c++ chapter1 2_dcshin
Effective c++ chapter1 2_dcshinEffective c++ chapter1 2_dcshin
Effective c++ chapter1 2_dcshinDong Chan Shin
 
Effective c++ chapter7_8_9_dcshin
Effective c++ chapter7_8_9_dcshinEffective c++ chapter7_8_9_dcshin
Effective c++ chapter7_8_9_dcshinDong Chan Shin
 
[C언어]함수오버로딩과오버라이딩
[C언어]함수오버로딩과오버라이딩[C언어]함수오버로딩과오버라이딩
[C언어]함수오버로딩과오버라이딩jusingame
 
More effective c++ 3
More effective c++ 3More effective c++ 3
More effective c++ 3현찬 양
 
C++ 2학기 수행평가
C++ 2학기 수행평가C++ 2학기 수행평가
C++ 2학기 수행평가Jaehee Lee
 
More effective c++ 2
More effective c++ 2More effective c++ 2
More effective c++ 2현찬 양
 

Ähnlich wie Chapter5 ~ 6 (19)

이펙티브 C++ 5,6 장 스터디
이펙티브 C++ 5,6 장 스터디이펙티브 C++ 5,6 장 스터디
이펙티브 C++ 5,6 장 스터디
 
Effective cpp
Effective cppEffective cpp
Effective cpp
 
Effective c++ chapter 1,2 요약
Effective c++ chapter 1,2 요약Effective c++ chapter 1,2 요약
Effective c++ chapter 1,2 요약
 
Effective C++ Chapter 1 Summary
Effective C++ Chapter 1 SummaryEffective C++ Chapter 1 Summary
Effective C++ Chapter 1 Summary
 
Effective c++ 정리 chapter 4
Effective c++ 정리 chapter 4Effective c++ 정리 chapter 4
Effective c++ 정리 chapter 4
 
More Effective C++ 4주차
More Effective C++ 4주차More Effective C++ 4주차
More Effective C++ 4주차
 
Effective c++ chapter 7,8
Effective c++ chapter 7,8Effective c++ chapter 7,8
Effective c++ chapter 7,8
 
The c++ programming language 10장 클래스 발표
The c++ programming language 10장 클래스 발표The c++ programming language 10장 클래스 발표
The c++ programming language 10장 클래스 발표
 
연산자 오버로딩
연산자 오버로딩연산자 오버로딩
연산자 오버로딩
 
Effective java
Effective javaEffective java
Effective java
 
EC 789
EC 789EC 789
EC 789
 
[아꿈사] The C++ Programming Language 13장 템플릿
[아꿈사] The C++ Programming Language 13장 템플릿[아꿈사] The C++ Programming Language 13장 템플릿
[아꿈사] The C++ Programming Language 13장 템플릿
 
Cpp에서 활용해보는 Lambda식
Cpp에서 활용해보는 Lambda식Cpp에서 활용해보는 Lambda식
Cpp에서 활용해보는 Lambda식
 
Effective c++ chapter1 2_dcshin
Effective c++ chapter1 2_dcshinEffective c++ chapter1 2_dcshin
Effective c++ chapter1 2_dcshin
 
Effective c++ chapter7_8_9_dcshin
Effective c++ chapter7_8_9_dcshinEffective c++ chapter7_8_9_dcshin
Effective c++ chapter7_8_9_dcshin
 
[C언어]함수오버로딩과오버라이딩
[C언어]함수오버로딩과오버라이딩[C언어]함수오버로딩과오버라이딩
[C언어]함수오버로딩과오버라이딩
 
More effective c++ 3
More effective c++ 3More effective c++ 3
More effective c++ 3
 
C++ 2학기 수행평가
C++ 2학기 수행평가C++ 2학기 수행평가
C++ 2학기 수행평가
 
More effective c++ 2
More effective c++ 2More effective c++ 2
More effective c++ 2
 

Kürzlich hochgeladen

코딩테스트 합격자 되기 C++ 03장(시간 복잡도)를 설명한 ppt입니다
코딩테스트 합격자 되기 C++ 03장(시간 복잡도)를 설명한 ppt입니다코딩테스트 합격자 되기 C++ 03장(시간 복잡도)를 설명한 ppt입니다
코딩테스트 합격자 되기 C++ 03장(시간 복잡도)를 설명한 ppt입니다ultrasuperrok
 
바리스타이론기초-1 수정 후 111111111111111111111111
바리스타이론기초-1 수정 후 111111111111111111111111바리스타이론기초-1 수정 후 111111111111111111111111
바리스타이론기초-1 수정 후 111111111111111111111111a01091282057
 
친환경, 그린, 탄소저감 미래 교육 공간 디자인의 이해와 사례들에 대한 강의 자료
친환경, 그린, 탄소저감  미래 교육 공간 디자인의 이해와 사례들에 대한 강의 자료친환경, 그린, 탄소저감  미래 교육 공간 디자인의 이해와 사례들에 대한 강의 자료
친환경, 그린, 탄소저감 미래 교육 공간 디자인의 이해와 사례들에 대한 강의 자료Seongwon Kim
 
TDM(Text Data Mining) Studio manual(2024)
TDM(Text Data Mining) Studio manual(2024)TDM(Text Data Mining) Studio manual(2024)
TDM(Text Data Mining) Studio manual(2024)yonseilibrary
 
이번에 새로 나온 코딩 테스트 합격자 되기 C++편 책을 소개하는 PPT 입니다.
이번에 새로 나온 코딩 테스트 합격자 되기 C++편 책을 소개하는 PPT 입니다.이번에 새로 나온 코딩 테스트 합격자 되기 C++편 책을 소개하는 PPT 입니다.
이번에 새로 나온 코딩 테스트 합격자 되기 C++편 책을 소개하는 PPT 입니다.ultrasuperrok
 
코딩 테스트 합격자 되기 C++ 00장~ 01장을 정리한 강의자료 입니다.
코딩 테스트 합격자 되기 C++ 00장~ 01장을 정리한 강의자료 입니다.코딩 테스트 합격자 되기 C++ 00장~ 01장을 정리한 강의자료 입니다.
코딩 테스트 합격자 되기 C++ 00장~ 01장을 정리한 강의자료 입니다.ultrasuperrok
 

Kürzlich hochgeladen (6)

코딩테스트 합격자 되기 C++ 03장(시간 복잡도)를 설명한 ppt입니다
코딩테스트 합격자 되기 C++ 03장(시간 복잡도)를 설명한 ppt입니다코딩테스트 합격자 되기 C++ 03장(시간 복잡도)를 설명한 ppt입니다
코딩테스트 합격자 되기 C++ 03장(시간 복잡도)를 설명한 ppt입니다
 
바리스타이론기초-1 수정 후 111111111111111111111111
바리스타이론기초-1 수정 후 111111111111111111111111바리스타이론기초-1 수정 후 111111111111111111111111
바리스타이론기초-1 수정 후 111111111111111111111111
 
친환경, 그린, 탄소저감 미래 교육 공간 디자인의 이해와 사례들에 대한 강의 자료
친환경, 그린, 탄소저감  미래 교육 공간 디자인의 이해와 사례들에 대한 강의 자료친환경, 그린, 탄소저감  미래 교육 공간 디자인의 이해와 사례들에 대한 강의 자료
친환경, 그린, 탄소저감 미래 교육 공간 디자인의 이해와 사례들에 대한 강의 자료
 
TDM(Text Data Mining) Studio manual(2024)
TDM(Text Data Mining) Studio manual(2024)TDM(Text Data Mining) Studio manual(2024)
TDM(Text Data Mining) Studio manual(2024)
 
이번에 새로 나온 코딩 테스트 합격자 되기 C++편 책을 소개하는 PPT 입니다.
이번에 새로 나온 코딩 테스트 합격자 되기 C++편 책을 소개하는 PPT 입니다.이번에 새로 나온 코딩 테스트 합격자 되기 C++편 책을 소개하는 PPT 입니다.
이번에 새로 나온 코딩 테스트 합격자 되기 C++편 책을 소개하는 PPT 입니다.
 
코딩 테스트 합격자 되기 C++ 00장~ 01장을 정리한 강의자료 입니다.
코딩 테스트 합격자 되기 C++ 00장~ 01장을 정리한 강의자료 입니다.코딩 테스트 합격자 되기 C++ 00장~ 01장을 정리한 강의자료 입니다.
코딩 테스트 합격자 되기 C++ 00장~ 01장을 정리한 강의자료 입니다.
 

Chapter5 ~ 6

  • 2. 항목 26 : 변수 정의는 늦출 수 있 는 데까지 늦추자 • 생성자 혹은 소멸자를 끌고 다 니는 타입으로 변수를 정의하 면 반드시 생성자 호출, 소멸 자 호출을 하는데 들어가는 비 용이 생긴다. • 변수가 정의되었는데 상요되 지 않을 경우에도 쓸데없는 비 용이 생긴다. • ->사용될 줄 알고 생성한 변수 가 사용이 안되는 경우가 생길 수 있다. • 언뜻 보면 encrypted가 반드시 사용되는 변수인 것 같지만 if 문에서 걸리면 사용되지 않는 변수가 된 다.
  • 3. 변수 정의는 꼭 필요해질 때 하자 • 조건에 걸려버리면 encrypted 는 쓸모없는 변수가 되어버리 므로, 꼭 필요해지기 전까지 encrypted의 정의는 미루는 것 이 좋다. • encrypted가 사용 될 수 있는 시점에 와야 비로소 변수로서 의미를 가지므로 다음과 같이 선언하면 변수 낭비의 비용이 발생하지 않는다.
  • 4. • 주의할 점은 루프안에서의 문제인데 이때는 A : 루프 바깥족에 정의 -> 생성자 1 + 소멸자 1 + 대입 n B : 루프 안쪽에서 정의 ->생성자 n + 소멸자 n 두 방법의 효율을 따져서 정한다. 정의와 동시와 초기화를 하는게 좋다 • 초기화 인자를 손에 넣기 전까 지 정의를 늦출 수 있는지 보 아야 한다. -> 대입연산자를 이용하면 초 기화를 이용하는 것보다 비용 이 더 들어가기 때문에, 정의 와 동시에 초기화를 하면 기본 생성자 호출의 낭비를 막을 수 있다. • 루프안에서는 일반적으로는 루프 바깥족에서의 정의하는 것이 효율이 좋다(대입에 들어 가는 비용이 생성자-소멸자 쌍 보다 더 적을 경우가 많다)
  • 5. 항목 26 정리 • 변수 정의는 늦출 수 있는 때까지 늦추자 • 초기화 인자가 나올때까지, 객체 정의를 늦추자 • 루프안에서의 변수 정의는 케이스 바이 케이스 로 효율을 따져서 결정하자
  • 6. 항목 27 : 캐스팅은 절약, 또 절약 • 캐스트에 항상 주의해야 한다. • C스타일의 캐스트, C++스타 일의 캐스트 중 C++ 스타일의 캐스트를 쓰는 것이 더 좋다 -> 어떤 것인지 알아보기 쉽고 , 캐스트의 사용목적을 좀더 명확하게 알아 볼 수 있다. • c스타일의 캐스트와, c++스타일의 static_cast를 통 해 double 타입의 a를 int타입으로 강제 형변환 시 켜준 예시
  • 7. C와 C++에서의 캐스팅 문법 • 될 수 있으면 C++ 의 캐스팅 방법을 쓰는 것이 좋다!
  • 8. 실수하기 쉬운 캐스팅 • 가상 함수를 파생 클래스에서 재정의해서 구현할 때 기본 클 래스의 버전을 호출을 먼저 할 때 -> static_cast를 이용한 this 객체는 임시객체이므로 의도 한대로 함수호출이 되지 않는 다.
  • 9. 다운캐스팅 시 주의 • 폭포식 dynamic_cast를 쓰지 말 것!
  • 10. 다운 캐스팅 없이 파생된 클 래스타입의 컨테이너를 이 용
  • 11. 다운 캐스팅 없이 가상함수 집합으로 기본 클래스에 넣 어두기
  • 12. 항목 27 정리 • 되도록이면 캐스팅을 피하자 • dynamic_cast는 정말 신중하게 쓰자. • 캐스팅이 반드시 필요하다면 함수 안에 숨길수 있도록 하자 • C 스타일보다 C++ 스타일의 캐스트를 쓰도록 하 자
  • 13. 항목 28 : 내부에서 사용하는 객 체에 대한 ‘핸들’을 반환하는 코드 는 피하자• 클래스 멤버 데이터는 그 멤버 의 참조자를 반환하는 함수들 의 접근도에 따라 캡슐화가 정 해진다. • 참조자 뿐만 아니라 핸들(참조 자, 포인터, 반복자 처럼 다른 객체에 손을 댈 수 있게 하는 매개자)을 반환하게 만들면 캡 슐화가 보장되지 않는다. • 특히 private로 외부 공개가 금 지된 데이터에 대해서 핸들을 반환할 시 그 캡슐화가 깨질 수 있기때문에 주의해야 한다. • 핸들을 반환하는 코드는 사용하면 안된다.
  • 14. 반환타입에 const를 붙이면 수정 불가하게 만들 수 있다 • const키워드를 붙임으로써 오직 읽도록만 할 수 있다.
  • 15. 항목 28 정리 • 어떤 객체의 내부요소에 대한 핸들( 참조자, 포인 터, 반복자)를 반환하는 것은 피하자 • 무효참조 핸들이 생기는 경우를 최소화 하자. • 캡슐화 정도를 높이기 위해서 핸들 반환하는 것 을 피하자
  • 16. 항목 29 : 예외 안전성이 확 보되도록 하자• 강력한 보장 : 함수 동작 중에 예외가 발생하면, 프로그램의 상태를 절대로 변경하지 않겠다는 보장. 이런 함수를 호출하는 것은 원자적인 동작 이라 한다. • 예외불가 보장 : 예외를 절대로 던지지 않겠다는 보장. 약속한 동작은 언제나 끝까지 완수하는 함 수 • 기본적인 보장 : 함수 동작 중에 예외가 발생하면 , 실행 중인 프로그램에 관련된 모든 것들을 유요 한 상태로 유지. 어떤 객체나 자료구조도 더럽히 지 않으며, 일관성을 유지하게 한다.
  • 17. 항목 29 정리 • 예외 안전성을 갖춘 함수는 실행 중 예외가 발생되 더라도 자원을 누출시키지 않는다. • 예외 안전성 보장은 기본적인 보장, 강력한 보장, 예외 금지 보장이 있다. • 강력한 예외 안전성 보장은 ‘복사-후-맞바꾸기’ 방 법을 써서 구현, 모든 함수에 대해 실용적인 것은 아니다. • 어떤 함수가 제공하는 예외 안전성 보장의 강도는 그 함수가 내부적으로 호출하는 함수들이 제공하 는 가장 약한 보장을 넘지 않는다.
  • 18. 항목 30 : 인라인 함수는 잘 따져 서 이해하자• 인라인 함수는 함수 호출문을 그 함수의 본문으로 바꿔치기 • 함수 호출 비용이 면제 • 메모리가 제한된 프로그램에서 는 코드가 커져서 문제가 발생할 수 있음 • inline은 컴파일러에 대해 ‘요청’ 이지 ‘명령’이 아님 • 암시적인 인라인 방법은 클래스 정의 안에 함수를 바로 구현(정 의) • 명시적인 방법에는 함수 정의 앞 에 inline키워드를 붙임 • GetAge멤버함수는 클래스 정의 내부에서 구현되 어있고, 이것은 곧 암시적인 인라인 요청을 하는 것 임을 뜻한다. • Max함수라는 것은 명시적으로 inline키워드를 써서 인라인함수 요청을 컴파일러에게 했다.
  • 19. C++에서의 인라인 함수 • 대부분의 C++ 프로그램에서 함수 인라인은 컴파일 타임에 진행 • 인라인이 끌고 오는 비용은 바로 코드 비대화 • 대부분의 컴파일러의 경우 아무리 인라인 함수로 선언(요청)을 했다 하더 라도, 컴파일러 자신이 보기에 복잡하거나 인라인에 적합하지 않다면 절 대로 인라인의 대상에 넣지 않음 • 가상함수는 절대로 인라인 해주지 않음 ->virtual의 의미는 어떤 함수를 호출할지 결정하는 작업을 실행중에 한다 는 것인데 인라인은 그 위치에 호출된 함수를 끼워넣는 작업이다. 컴파일 러는 실행전에 그 위치에 함수의 코드를 끼워 넣어야 되는데 그 함수가 어 떤건지 알 수 없다. • 생성자와 소멸자는 인라인하기에 좋지않다. ->동적으로 만들었다면 생성자에서 초기화 해주거나, 상속을 받았다면 기 본 클래스의 생성자를 호출해 준다든가, 멤버 데이터들을 초기화해준다거 나 하는 일들을 한다. 이런것들을 전부 인라인으로 처리해 버리면 호출되 는 함수들이 전부 코드로 들어가버리므로 똑같은 함수들을 여러개 가지는 꼴이 되어버릴 수 있다.
  • 20. 항목 30 정리 • 함수 인라인은 작고, 자주 호출되는 함수에 대해 서만 하자 -> 디버깅 및 라이브러리의 업그레이드가 용이, 프로그램의 속도가 빨라질 가능성이 있음 • 되도록이면 아무것도 인라인하지말고( 컴파일러 가 알아서 인라인으로 적합한 것은 인라인으로 바꾸어줌), 인라인해야하는 경우는 정말 단순한 함수에 한해서만 해줌
  • 21. 항목 31 : 파일 사이의 컴파일 의 존성을 최대로 줄이자 • 어떤 것이 컴파일 되려면 그것 에 속한 정보들이 있어야 하는 데 이때 쓰이는 지시자가 #include이다. • #include는 파일과 헤더파일 들 사이에 컴파일 의존성을 엮 어버린다. 즉 이것에 엮여 있 는 모든 것들이 이것에 의존하 게 되는 것이다. • 의존성이 높아져버리면 컴파 일이 꼬리에 꼬리를 물어 굉장 한 성능저하를 가져올 수 있다 . • 위의코드만 가지고 Person클래스가 컴파일 되지 않는다. Person의 구현의 한 부분인 string, Date, Address등 연관된 것들의 정보가 있어야 컴파일 된 다. 이때 쓰는 것이 #include 지시자이다. 즉 #include “date.h”, #include “address.h”, #include <string> 선언되어야 한다.
  • 22. 인터페이스와 구현을 둘로 나누 자• 정의부에 대한 의존성을 선언 부에 대한 의존성으로 바꿈 -> 컴파일 의존성을 최소화하 는 원리 • 객체 참조자 및 포인터로 충분 한 경우 객체를 직접 쓰지 않 는다. • 할 수 있으면 클래스 정의 대 신 클래스 선언에 최대한 의존 하도록 한다. ->클래스를 사용하는 함수를 선언할 때는 그 클래스의 정의 는 굳이 가져오지 않아도 된다 . • 선언부와 정의부에 대해 별도 의 헤더파일 제공 • 어떤 클래스를 사용하는 함수를 선언할 때는 그 정 의는 필요 없음 • 또는 이렇게 헤더파일을 만드는데 선언만 되어있는 헤더파일만으로도 가능
  • 23. 항목 31 정리 • 컴파일 의존성을 최소화하자 • 컴파일 의존성을 최소화하는 아이디어 -> ‘정의’ 대신에 ‘선언’에 의존하게 만들자 • 라이브러리 헤더는 그 자체로 모든 것을 가줓어 야 하며 선언부만 갖고 있는 형태여야 한다.
  • 24. 항목 32 : public상속은 is-a관계 • public 상속은 “is-a”를 의미한 다 • Cat클래스를 Animal 클래스로 부터 상속을 통해 파생시켰다 면 이 뜻은 ‘Cat 타입으로 만들 어진 모든 객체는 Animal타입 의 객체이지만 그 반대는 성립 하지 않는다’ 이다 • Animal객체가 쓰일 수 있는 모 든 곳에는 Cat객체도 쓰일 수 있다고 단정하는 것 • cat is a Animal 이 되지만 반대인 Animal is cat은 말이 안된다.
  • 25. 항목 32 : public상속은 is-a관계 • Bird 객체인 a는 수영을 할 수 없다. • Penguin 객체인 b는 수영을 할 수 있다. • Penguin객체인 b는 날 수 없 지만 Bird에 기본 함수는 날 수 있다고 되어있기에, 가상함수 를 이용하여 재정의 -> 인간의 언어 때문에 클래스 설계에 있어 오류를 범하는 경 우가 많이 있다. 설계시 주의 해야 하는 사항
  • 26. 항목 31 정리 • public 상속의 의미는 “is-a” 관계이다. 기본 클래 스에 적용되는 모든 것들이 파생 클래스에도 그 대로 적용이 된다. -> 이는 파생 클래스 객체도 기본객체의 일종으 로 보기 때문이다.
  • 27. 항목 33 : 상속된 이름을 숨기는 일을 피하자 • C++ 컴파일러는 유효범위 안 에서 어떤 변수의 이름을 만나 면 일단 자신이 처리하는 유효 범위를 뒤져서 같은 이름이 있 는지 확인. • 그 유효범위에 있으면 더이상 탐색하지 않음 • 그 유효범위에 없다면 다음 영 역의 유효범위를 탐색 • 컴파일러는 자신이 처리하고있는 곳의 유효범위부 터 탐색해 나간다.
  • 28. 클래스에서의 이름 가리기 • 파생 클래스 Dervied 의 mf1은 Base의 mf1(int)를 가린다. • 파생 클래스 Dervied 의 mf3 는 Base의 mf3(), mf3(double) 을 가린다. -> 이러한 이유는 파생클래스 에서 멀리 떨어져 있는 기본 클래스의 오버로드 버전을 상 속하는 것을 ‘실수’로 간주하 겠다는 컴파일러의 의도 때문 이다. • Derived클래스의 mf1, mf3로 인해 오버로드 된 Base 클래스의 mf1, mf3또한 가려지게 된다.
  • 29. using 키워드 이용 • 파생 클래스에 의해 가려진 기 본 클래스의 오버로드된 함수 들은 using 키워드를 통해 끄 집어낼 수 있다. • 즉, 오버로드된 함수들 중에 재정의를 하고 싶은것이 있다 면 파생클래스에서 재정의를 하고, using 키워드를 붙여주 면 된다. • using 키워드를 통하여 기본클래스의 mf1, mf3의 이름이 derived영역에서도 유효하게 되었다
  • 30. 항목 33 정리 • 파생 클래스의 이름은 기본 클래스의 이름을 가 린다 • public 상속에서의 이런 이름 가림 현상은 바람직 하지 않다 • 가려진 이름을 다시 볼 수 있게 하는 방법으로 using 선언 혹은 전달 함수를 쓸 수 있다.
  • 31. 항목 34 : 인터페이스 상속과 구 현상속의 차이 알기 • pubilc상속의 개념은 함수 인 터페이스의 상속과 더불의 함 수 구현의 상속 • 인터페이스 -> 함수의 선언 구현 -> 함수의 정의 • public으로 상속을 받았다는 것은 기본적으로 인터 페이스 + 구현 까지 상속을 받은 것이다. Derived 는 Base를 public으로 상속받으므로 Base의 인터 페이스 및 구현을 상속 받은 것.
  • 32. 순수가상 함수는 인터페이스 상 속을 뜻한다 • 순수 가상 함수를 상속받는 파 생 클래스에서는 그 가상함수 를 다시 선언해야 한다. • 순수 가상 함수는 전형적으로 추상 클래스 안에서는 정의를 갖지 않는다. • 순수 가상 함수를 선언하는 목 적은 파생 클래스에게 함수의 인터페이스만을 물려주는 것. • 부모 클래스인 Shape에서 Draw는 순수 가상 함수 로 선언. 즉 파생클래스인 Triangle에서 다시 선언 및 구현을 해주어야 한다.
  • 33. 비순수가상 함수는 인터페이스 상속 과 더불어 그 함수의 기본적 구현을 물려받게 함 • 비순수 가상 함수는 인터페이 스와 더불어 기본적 구현을 물 려받게 하는 방법 • 파생 클래스에서 따로 재정의 하지 않아도 된다 ->기본적 구현을 물려받았기 때문에 • 파생클래스에서 따로 재정의 해도 된다 -> 가상함수로 인터페이스 상 속과 더불어 구체적인 구현도 가능하기 때문에 • 기본 클래스의 Error은 비순수가상 함수로 이에대 한 인터페이스와 기본적인 구현을 물려받음
  • 34. 비가상 함수는 인터페이스와 필 수적인 구현까지 물려받음 • 비가상 함수를 선언하는 목적 은 파생 클래스가 함수 인터페 이스와 더불어 그 함수의 필수 적인 구현을 물려받게 하는 것 • 비가상 함수는 클래스 파생에 관계없이 동작에 있어 변하는 것이 없을 때 사용 • 즉, 파생클래스에서 재정의 하 는 것이 아니다. • SetName과 GetShapeName함수는 비가상 함수인 데, 파생클래스라 하더라도 이름을 정하고 받아오 는 함수는 동작에 변화가 없으므로 비가상 함수로 선언.
  • 35. 항목 34 정리 • 인터페이스 상속은 구현상속과 다르다 • public상속은 기본 클래스의 인터페이스를 모두 물려 받는다 • 순수 가상 함수는 인터페이스만 상속 • 비순수 가상 함수는 인터페이스 상속과 더불어 기본 구현의 상속도 가능 • 비가상 함수는 인터페이스 상속과 더불어 필수 구현의 상속
  • 36. 항목 35 : 가상 함수 대신 쓸 것들 도 생각해두자 • 비가상 인터페이스 관용구를 사용하자 : 공개되 지 않은 가상 함수를 비가상 public멤버 함수로 감싸서 호출 • 가상 함수를 함수 포인터 데이터 멤버로 대체하 자 • 가상 함수를 tr1::function 데이터 멤버로 대체하 여 호환되는 시그너처를 가진 함수호출성 개체 를 사용할 수 있도록 하자 • 한쪽 클래스 계통에 속해 있는 가상 함수를 다른 쪽 계통에 속해 있는 가상 함수로 대체하자
  • 37. 항목 35 정리 • 가상 함수 대신에 쓸 수 있는 다른 방법으로 NVI 관용구 및 전략 패턴을 들 수 있다 이중 NVI 관용 구는 그 자체가 템플릿 메서드 패턴의 한 예시 • 객체에 필요한 기능을 멤버 함수로부터 클래스 외부의 비멤버 함수로 옮기면, 그 비멤버 함수는 그 클래스의 public 멤버가 아닌 것들을 접근할 수 없다는 단점이 생김 • tr1::function 객체는 일반화된 함수 포인터처럼 동작. 이 객체는 주어진 대상 시그너처와 호환되 는 모든 함수호출성 개체 지원
  • 38. 항목 36 : 상속받은 비가상 함수를 파생 클래스에서 재정의하는 것은 절대 금물• 비가상 함수는 정적 바인딩 -> 빌드 중에 이름, 식별자, 값, 속 성들의 내부요소를 정의. • 가상 함수는 동적 바인딩 -> 실행중에 이름, 식별자, 값, 속성 들의 내부요소를 정의. • 자기 자신의 객체가 아닌 객체를 가리키는 포인터 타입에 의해 어떤 함수를 호출할 지 결정. • 비가상 함수를 public으로 상속받 으면 인터페이스와 필수 구현을 그 대로 물려받음 -> 파생클래스에서 재정의하는 것은 모순(Triange is a Shape이 성립하지 않음) • Shape클래스에서 비가상 함수를 구현하고 이를 Triangle클래스가 상속을 받았는데, 다시 그 비가상 함수를 재정의 하고 있다. 해당 객체 자신( Triangle 객체 a ) 이 아닌 그것을 가리키는 포인터 pT에 의 해 좌우된다.
  • 39. 항목 36 정리 • 상속받은 비가상 함수를 재정의하는 일은 절대 로 하면 안된다. • public상속 관계의 “is- a” 관계에 모순이 생김 • 재정의 할 필요가 있는 함수라면 가상 함수로 정 의하는 것이 맞다.
  • 40. 항목 37: 어떤 함수에 대해서도 상속 받은 기본 매개변수 값은 절대로 재정 의하지말자 • 비가상 함수는 정적 바인딩 -> 빌드 중에 이름, 식별자, 값, 속성들의 내부요소를 정의. • 가상 함수는 동적 바인딩 -> 실행중에 이름, 식별자, 값, 속성들의 내부요소를 정의. • 기본 매개변수는 정적 바인딩 • Triangle의 객체를 생성해서 Triangle의 func() 를 실행하면 size = 1이 되어 나온다. 즉, Triangle클래 스에서 매개변수를 재정의한 것이 의미가 없다는 것이다.(매개변수는 기본 클래스 것을 이용) -> 꼬 여버림
  • 41. 비가상 인터페이스를 이용하여 해결 • 파생 클래스에서 재정의할 수 있는 가상 함수를 private 멤버 로 둔다. • 이 가상 함수를 호출하는 public비가상 함수를 기본 클 래스에 만든다. • 비가상 함수가 기본 매개변수 를 지정할 수 있게 한다. • func를 비가상함수로 만들고, 재정의할 수 있는 함 수 Dofunc를 만들어 호출. 비가상 함수가 기본 매개 변수를 지정하도록 할 수 있음.
  • 42. 항목 37 정리 • 상속받은 기본 매개변수 값은 절대로 재정의하 면 안된다. • 기본 매개변수는 정적으로 바인딩 • 가상함수는 동적으로 바인딩 • 함수호출이 꼬여버리는 경우가 생길 수 있다.
  • 43. 항목 38: “has-a”혹은 “is-implemented-in- terms-of”를 모형화할 때는 객체 합성을 사용 • 합성이란 어떤 타립의 객체들 이 그와 다른 타입의 객체들을 포함하고 있을 경우에 성립하 는 그 타입들 사이의 관계 • 합성 대신에 레이어링, 포함, 통합, 내장 등으로도 쓴다. • …has a~ : …은 ~를 가진다 • …is-implemented-in-terms- of~ : …은 ~를 써서 구현된다. • Person 객체는 이름, 주소, 핸드폰전화번호 등을 가지고 있는 객체이므로, Person과 string m_Name, Address m_Address, PhoneNumber m_celPhone 은 “has - a “ 관계. • Person has a name; • Person has a Address;
  • 44. 과 • public 으로 상속을 받는다면 이는 is-a관계이다. • STL의 set 클래스를 만드는데 list STL을 이용하고자 한다. • 이때 set 은 set is-implemented-in-terms- of list가 되는 것이고 이 두 관 계가 되는 것이다. • 위의 관계로 is-a로 해석해버리면 set is a list가 되 어야 하는데 list 는 중복을 허용하지만 set은 그렇 지 않다. 즉 성립하지 않음을 알 수 있다. • 밑의 관계로 is-implemented-in-terms-of가 되면 set 은 list를 이용하여 만들어졌다 로 자연스럽게 해석 할 수 있다.
  • 45. 항목 38 정리 • 객체 합성의 의미는 public 상속이 가진 의미와 완전히 다르다 • 응용 영역에서 객체 합성의 의미는 has-a 이다 • 구현 영역에서 객체 합성의 의미는 is- implemented-in-terms-of이다.
  • 46. 항목 39: private 상속은 심사숙고 해서 구사하자 • private 상속은 분명히 is-a를 뜻하지 않는다. • private로 상속 받으면 컴파일 러는 일반적으로 파생 클래스 객체를 기본 클래스 객체로 변 환하지 않는다. • 기본 클래스로부터 물려받은 멤버는 파생 클래스에서 모조 리 private멤버가 된다. • private상속의 의미는 is- implemented-in-terms-of, 인터 페이스는 물려받지 못하고 구 현만 물려받을 수 있다. • S는 더이상 Person으로 간주되지 않는다. 다만 S 는 Person의 몇 가지 특성을 사용한다는 뜻이다.
  • 47. 객체 합성과 private상속의 차이 • 객체 합성도 is-implemented- in-terms-of의 관계를 갖는다. • 되도록이면 객체 합성을 사용 하고, 꼭 필요한 경우에만 private사용 -> 꼭 필요한 경우라 하면 비 공개 멤버를 접근할 때 혹은 가상 함수를 재정의할 경우. • 어떤 클래스에서 필요한 기능 이 있는데 이것을 public상속 을 받는다면 is-a 관계가 되어 모순이 일어난다. 따라서 이렇 게 어떤 기능을 이용할 때에는 private 상속을 받을 수 밖에 없다. • private상속은 public상속과 객체합성을 이용하여 피할 수 있다. 하지만 관계는 더 복잡해진다.
  • 48. 항목 39 정리 • private상속의 의미는 is-implemented-in-terms- of이다 • 파생 클래스 쪽에서 기본 클래스의 protected 멤 버에 접근해야 할 경우, 상속받은 가상 함수를 재 정의해야 할 경우에 private 상속을 고려해보아 야 함 • 객체 합성과 달리, private 상속은 공백 기본 클래 스 최적화(EBO)를 활성화시킬 수 있다.
  • 49. 항목 40: 다중 상속은 심사숙고해 서 사용하자 • 다중 상속은 단일 상속보다 구 조가 복잡 • 다중 상속하면 둘 이상의 기본 클래스로부터 똑같은 이름( 멤 버 함수, 멤버 변수 등 )을 물 려받을 가능성이 생긴다. • Son 객체인 me는 Father 와 Mother의 다중 상속을 받고 있고, 다시 Father 와 Mother 는 Person으로 부터 단일 상속을 받는다. 이때 Son 객체의 Do()를 호출 하면 Father의 것인지 Mother의 것인지 알 수 없기에 에러가 발생한다.
  • 50. 모호성을 없애기 위해 호출할 기 본 클래스의 함수를 손수 지정• 모호성을 없애기 위해 호출할 기본 클래스를 지정해주어야 한다. • 만약 데이터멤버의 중복생성 을 원한 것이 아니었다면 데이 터 멤버를 가진 클래스를 가상 기본 클래스로 만들어야 한다. -> 기본 클래스가 상속되는 경 로 갯수만큼 데이터가 중복생 성 되는 걸 막기 위해서 • 가상 상속을 사용하는 클래스 는 가상 상속을 쓰지 않는 클 래스보다 크기가 크고, 속도도 느리다 -> 가상 상속은 비싸다 • me.Father::Do()로 호출할 기본 클래스를 지정해줌 으로써 어떤 함수를 호출할 지 컴파일러가 알게되 어, 호출이 된다.
  • 51. 가상 상속 • 가상 상속을 하지 않으면 Fater와 Mater 클래스를 다중상속 받는 Son객체가 생성 될 때 1. Father와 Mother 의 부모인 Person클래스가 각각 생성 2. Father와 Mother를 상속받음 • 만약 자식에서 Person의 허용된 데이터 및 함수를 읽고자 할 때, Father의 것인지, Mother의 것인지 알 수 없어서 모호함 -> 에러 • virtual 로 상속 받으면 Father와 Mother의 부모인 Person을 한 번 만 생성 -> 조상이 Person하나이 므로 Person의 허용된 데이터 및 함수 사용 가능 • 가상상속을 통하여 조상의 함수를 바로 호출 가능
  • 52. 항목 40 정리 • 다중 상속은 단일 상속보다 확실히 복잡하다 • 모호성이 생길 여지가 있다 • 가상 상속이 필요해질 때가 있는데, 가상 상속을 사용하면 크기, 속도 면에서 비가상 상속과 비교 하여 좋지 않다 • 가상 상속 시 가상 기본 클래스에는 데이터를 두 지 않는 것이 좋다 -> 초기화 및 대입 연산의 복 잡도가 커지기 때문에