SlideShare a Scribd company logo
Effective C++
Chapter6. 상속, 그리고 객체 지향 설계
Item32. public상속 모형은 반드시 is – a(뭐는 뭐의 일종이다)
• is - a의 정의:
 어떤 클래스 D(derived)를 클래스 B(Base)로부터 상속을 통해
파생시킨 경우
 D타입의 모든 객체는 동시에 B 타입의 객체이지만, 그 반대
는 성립하지 않는다.
 고로 B타입의 객체가 쓰일 수 있는 곳에는 D타입도 마찬가
지로 쓰일 수 있다.
 모든 D는 B의 일종이다(D is a B) 그 반대는 x
• C++과 자연어에서의 is – a관계 차이
• class Bird {
public:
virtual void fly(); // 새는 날 수 있다.
};
• class Penguin: public Bird { // 펭귄은 새다.
. . .
};
 새는 날 수 있다고 했지만 펭귄은 날지 못하는데…
Item32. public상속 모형은 반드시 is – a(뭐는 뭐의 일종이다)
• 해결책 1: 새 종류의 구체화
• class Bird{
. . . // fly 함수 선언x
};
• class FlyingBird : public Bird{
virtual void fly(); //날 수 있는 새의 fly함수 선언
. . .
};
• class Penguin : public Bird{
. . . //Penguin은 일반 Bird클래스 상속으로 선언x
};
Item32. public상속 모형은 반드시 is – a(뭐는 뭐의 일종이다)
• 해결책2: 펭귄의 날기에 대한 에러처리
• Class Penguin : public Bird{
public:
virtual void fly() { error{“Attempt to make a penguin fly!”); }
. . .
};
혹은 Penguin의 fly구현 자체를 안 하는 방법도 있지만
유효하지 않은 코드는 컴파일 단계에서 막아주는게 좋음
(Item18)
이렇듯 자연어 is-a관계와 헷갈리면 안된다.
Item32. public상속 모형은 반드시 is – a(뭐는 뭐의 일종이다)
Item33. 상속된 이름을 숨기지 말자
• 유효범위(scope)
• int x; //전역 변수
• void someFunc()
{
double x; // 지역 변수
std::cin >> x; // 입력을 받아, 지역 변수 x에 새 값을 읽어 넣는다.
}
C++의 이름 가리기 규칙에 의해 자신이 처리하고 있는 유효
범위에 같은 이름인 x가 있기 때문에 더 이상 탐색하지 않는다.
Item33. 상속된 이름을 숨기지 말자
유효범위에서 컴파일러가 이름을 찾는 순서:
mf2를 찾는 경우 지역을 찾아보고 없으므로  Derived클래스 탐색 
Derived를 감싸고 있는 Base 탐색  여기서 mf2를 발견  만약 여기에도 없
었으면 마지막으로 전역을 탐색
Item33. 상속된 이름을 숨기지 말자
Derived의 mf1()과 mf3()가 Base로 부터 상속받은 것을 가
상이건 비가상이건, 모두다 가려 버린다. 또, 이름이 같은
함수이면 매개변수 타입이 달라도 가린다.
Item33. 상속된 이름을 숨기지 말자
이럴 때 using을 사용하여 본래 Base의 함수를 상속받을 수 있다.
Item34. 인터페이스 상속과 구현 상속의 차이를 구별하자
• 인터페이스 상속: 함수의 선언 부를 상속
• 구현 상속: 함수의 구현 부를 상속
• 여러 가지 상황에 따라 인터페이스 상속만 필요할 경우가 있고
구현 상속이 필요할 경우도 있다.
Item34. 인터페이스 상속과 구현 상속의 차이를 구별하자
Draw()함수가 바로 순수 가상 함수이고, error()는 가상 함수, objectID()는 비가상 함수 이
다.
• 순수 가상 함수
• 함수의 인터페이스 만을 물려주려는 것
• Shape::draw처럼 모든 객체는 그리기가 가능해야 하지만 모든
객체의 그리는 알고리즘이 같을 리가 없기 때문
(ex)직사각형 != 타원
Item34. 인터페이스 상속과 구현 상속의 차이를 구별하자
• 가상 함수
• 파생 클래스로 하여금 함수의 인터페이스뿐만 아니라 그 함수
의 기본 구현도 물려받게 하는 것
• Shape::error 처럼 기본 인터페이스를 제공 하면서 파생 객체에
서 error가 났을 때 Shape의 기본 error 구현을 가져다 사용 할
수 있게 한다. 만약 기본 클래스의 구현을 사용하고 싶지 않다면
파생 클래스 개별적으로 구현도 가능하다.
Item34. 인터페이스 상속과 구현 상속의 차이를 구별하자
• 비가상 함수
• Shape::objectID(), 클래스 파생에 상관없이 변하지 않는 동작에
쓰임
• 인터페이스와 그 함수의 필수적인 구현을 상속
• 파생 클래스에서 재정의 불가
Item34. 인터페이스 상속과 구현 상속의 차이를 구별하자
• 비가상 함수 인터페이스 (non-virtual-interface: NVI)
• Class GameCharacter{
public:
int healthValue() const
{
. . . // 사전 동작
int retVal = doHealthValue(); // privat의 가상함수를 호출
. . . // 사후 동작
return retVal;
}
private:
virtual int doHealthValue() const
{
. . .
}
Item35. 가상 함수 대신을 생각해 두자
사용자가 직접 가상함수를 호출 하지 않게 함
으로 써 사전 동작과 사후 동작 사이에서 가
상 함수를 호출 할 수 있게 되었다.
Item35. 가상 함수 대신을 생각해 두자
• std::function으로 구현한 전략 패턴 • std::function을 이용하여 함수 포인터
처럼 사용할 수 있다.
• HealthCalcFunc을 설정하는 함수를
따로두어 게임 진행 중에도 체력 계산
치를 바꾸어 줄 수 있다.
Item35. 가상 함수 대신을 생각해 두자
• 고전적인 전략 패턴
고전적인 전략 패턴으로 HealthCalcFunc 클래스 계통에 파생 클래스를 추가함으로써
기존의 체력치 계산 알고리즘을 조정/개조 할 가능성도 열어 두었다는 점은 플러스 이다.
Item36. 상속 받은 비가상 함수를 파생 클래스에서 재정의 X
• B로부터 파생된 클래스인 D에서 mf()함수를 재정의 하게 되면 기본 클래스의 mf()함수를
가리게 된다.
• 위 처럼 동작하는 이유는 비 가상 함수를 정적 바인딩이기 때문이다.
 pB는 B에대한 포인터로 선언 되었기 때문에 비 가상함수mf()가 반드시 B에 존재 할거
라 생각 하는 것이다.
• 또 파생클래스인 D에서 mf()를 호출 할 때 B의 mf()로 갈지 D의 mf()로 갈지 난해한 상황
Item37. 상속 받은 기본 매개변수 값은 절대 재정의 X
Item37. 상속 받은 기본 매개변수 값은 절대 재정의 X
pc의 동적타입은 Circle*
pr의 동적타입은 Rectangle*
가상 함수는 동적 바인딩 된다.
pr의 동적 타입은 Rectangle* 이므로 Rectangle의 draw함수를 불러 오지만 기본 매개변수
는 정적으로 바인딩 되기 때문에 정적 타입인 Shape*의 매개변수를 가져 오는 참사가 발
생하게 된다.
• 그래도 매개변수를 건들고 싶다면…
비가상 인터페이스 관용구(NVI)를 사용하자(Item 35)
 가상 함수를 private으로 두고 이를 호출하는 비가상 함수를
기본 클래스에 두는 방식
이를 이용하여 비가상 함수가 매개변수를 지정할 수 있게
할 수 있다.
Item37. 상속 받은 기본 매개변수 값은 절대 재정의 X
• 객체 합성: 어떤 타입의 객체가 다른 타입의 객체들을 포함하고
있는 관계
Item38. has a, is a 모형화할 때 객체합성을 이용하자
• 응용 영역: 객체 중 일상생활에서 볼 수 있는 것을 본뜬 것
(ex) 사람, 이동수단
• 구현 영역: 버퍼, 뮤텍스, 탐색트리등 시스템 구현만을 위한 인
공물이 속한 객체
• 객체 합성이 응용 영역에서 일어나면 has-a 관계
구현 영역에서 일어나면 is-implemented-in-terms-of 관계이다.
Item38. has a, is a 모형화할 때 객체합성을 이용하자
• has- a 관계
전에 보여주었던 Person과 Address의 관계
• is-implemented-in-terms-of 관계가 필요한 예
set 템플릿을 list에서 파생된 형태로 만들고 싶을 때
is-a 관계로 했더니 list의 중복 원소를 가질 수 있는 기본 성질
을 set에서는 적용할 수가 없다.
Item38. has a, is a 모형화할 때 객체합성을 이용하자
Item38. has a, is a 모형화할 때 객체합성을 이용하자
이러한 상황일 때 is-implemented-in-terms-of 관계를 이용하면
된다.

More Related Content

PPTX
Java standard(8~13)
PPTX
Refelction의 개념과 RTTR 라이브러리
PPTX
이펙티브 C++ 5,6 장 스터디
PDF
프로그래밍 대회: C++11 이야기
PDF
[Swift] Extensions
PDF
C++ Advanced 강의 4주차
PPTX
C++11
PPTX
C review
Java standard(8~13)
Refelction의 개념과 RTTR 라이브러리
이펙티브 C++ 5,6 장 스터디
프로그래밍 대회: C++11 이야기
[Swift] Extensions
C++ Advanced 강의 4주차
C++11
C review

What's hot (20)

PDF
[C++ Korea] Effective Modern C++ MVA item 9 Prefer alias declarations to type...
PPTX
Modern C++의 타입 추론과 람다, 컨셉
PPTX
Effective cpp
PDF
[C++ Korea] Effective Modern C++ MVA item 8 Prefer nullptr to 0 and null +윤석준
PPTX
[C++ korea] effective modern c++ study item8~10 정은식
PDF
C++ Advanced 강의 2주차
PDF
Haskell study 8
PDF
Effective c++ chapter1 2_dcshin
PPTX
C++11
PDF
2013 C++ Study For Students #1
PDF
C Language For Arduino
PPTX
Cpp에서 활용해보는 Lambda식
PPTX
C#을 사용한 빠른 툴 개발
PDF
[C++ Korea] Effective Modern C++ mva item 7 distinguish between and {} when c...
PDF
[C++ korea] effective modern c++ study item 7 distinguish between () and {} w...
PDF
C++ Advanced 강의 1주차
PDF
9 swift 클로저1
PDF
Effective Modern C++ MVA item 18 Use std::unique_ptr for exclusive-ownership ...
PDF
Haskell study 4
PPTX
Visual studio 2010
[C++ Korea] Effective Modern C++ MVA item 9 Prefer alias declarations to type...
Modern C++의 타입 추론과 람다, 컨셉
Effective cpp
[C++ Korea] Effective Modern C++ MVA item 8 Prefer nullptr to 0 and null +윤석준
[C++ korea] effective modern c++ study item8~10 정은식
C++ Advanced 강의 2주차
Haskell study 8
Effective c++ chapter1 2_dcshin
C++11
2013 C++ Study For Students #1
C Language For Arduino
Cpp에서 활용해보는 Lambda식
C#을 사용한 빠른 툴 개발
[C++ Korea] Effective Modern C++ mva item 7 distinguish between and {} when c...
[C++ korea] effective modern c++ study item 7 distinguish between () and {} w...
C++ Advanced 강의 1주차
9 swift 클로저1
Effective Modern C++ MVA item 18 Use std::unique_ptr for exclusive-ownership ...
Haskell study 4
Visual studio 2010
Ad

Similar to Effective c++ Chapter6 (20)

PPTX
Effective c++ 정리 chapter 6
PPTX
Chapter5 ~ 6
PPTX
Effective c++chapter4
PPTX
Effective c++(chapter 5,6)
PDF
5 6 1
PPTX
Effective c++ 3
PPTX
Effective c++chapter1 and2
PPTX
Effective c++ 정리 chapter 4
PDF
12장 상속 (고급)
PPTX
이펙티브 C++ 스터디
PDF
08장 객체와 클래스 (기본)
PDF
13th chapter12 slide
PDF
Effective c++ chapter5 6_ 131039 신동찬
PPTX
Effective c++ Chapter1,2
PDF
Effective c++ chapter 1,2 요약
PDF
Effective c++ item40
PPTX
11장 상속
PDF
9 object class
PPT
강의자료3
PDF
Tcpl 12장 파생클래스
Effective c++ 정리 chapter 6
Chapter5 ~ 6
Effective c++chapter4
Effective c++(chapter 5,6)
5 6 1
Effective c++ 3
Effective c++chapter1 and2
Effective c++ 정리 chapter 4
12장 상속 (고급)
이펙티브 C++ 스터디
08장 객체와 클래스 (기본)
13th chapter12 slide
Effective c++ chapter5 6_ 131039 신동찬
Effective c++ Chapter1,2
Effective c++ chapter 1,2 요약
Effective c++ item40
11장 상속
9 object class
강의자료3
Tcpl 12장 파생클래스
Ad

More from 세빈 정 (7)

PPTX
Gpg study3.7
PPTX
Gpg study1.8
PPTX
Effective c++ 1,2
PPTX
디자인 패턴(Observer, visitor)
PDF
소켓프로그래밍 기초요약
DOCX
Pac-man
PPTX
포스트모템1
Gpg study3.7
Gpg study1.8
Effective c++ 1,2
디자인 패턴(Observer, visitor)
소켓프로그래밍 기초요약
Pac-man
포스트모템1

Effective c++ Chapter6

  • 1. Effective C++ Chapter6. 상속, 그리고 객체 지향 설계
  • 2. Item32. public상속 모형은 반드시 is – a(뭐는 뭐의 일종이다) • is - a의 정의:  어떤 클래스 D(derived)를 클래스 B(Base)로부터 상속을 통해 파생시킨 경우  D타입의 모든 객체는 동시에 B 타입의 객체이지만, 그 반대 는 성립하지 않는다.  고로 B타입의 객체가 쓰일 수 있는 곳에는 D타입도 마찬가 지로 쓰일 수 있다.  모든 D는 B의 일종이다(D is a B) 그 반대는 x
  • 3. • C++과 자연어에서의 is – a관계 차이 • class Bird { public: virtual void fly(); // 새는 날 수 있다. }; • class Penguin: public Bird { // 펭귄은 새다. . . . };  새는 날 수 있다고 했지만 펭귄은 날지 못하는데… Item32. public상속 모형은 반드시 is – a(뭐는 뭐의 일종이다)
  • 4. • 해결책 1: 새 종류의 구체화 • class Bird{ . . . // fly 함수 선언x }; • class FlyingBird : public Bird{ virtual void fly(); //날 수 있는 새의 fly함수 선언 . . . }; • class Penguin : public Bird{ . . . //Penguin은 일반 Bird클래스 상속으로 선언x }; Item32. public상속 모형은 반드시 is – a(뭐는 뭐의 일종이다)
  • 5. • 해결책2: 펭귄의 날기에 대한 에러처리 • Class Penguin : public Bird{ public: virtual void fly() { error{“Attempt to make a penguin fly!”); } . . . }; 혹은 Penguin의 fly구현 자체를 안 하는 방법도 있지만 유효하지 않은 코드는 컴파일 단계에서 막아주는게 좋음 (Item18) 이렇듯 자연어 is-a관계와 헷갈리면 안된다. Item32. public상속 모형은 반드시 is – a(뭐는 뭐의 일종이다)
  • 6. Item33. 상속된 이름을 숨기지 말자 • 유효범위(scope) • int x; //전역 변수 • void someFunc() { double x; // 지역 변수 std::cin >> x; // 입력을 받아, 지역 변수 x에 새 값을 읽어 넣는다. } C++의 이름 가리기 규칙에 의해 자신이 처리하고 있는 유효 범위에 같은 이름인 x가 있기 때문에 더 이상 탐색하지 않는다.
  • 7. Item33. 상속된 이름을 숨기지 말자 유효범위에서 컴파일러가 이름을 찾는 순서: mf2를 찾는 경우 지역을 찾아보고 없으므로  Derived클래스 탐색  Derived를 감싸고 있는 Base 탐색  여기서 mf2를 발견  만약 여기에도 없 었으면 마지막으로 전역을 탐색
  • 8. Item33. 상속된 이름을 숨기지 말자 Derived의 mf1()과 mf3()가 Base로 부터 상속받은 것을 가 상이건 비가상이건, 모두다 가려 버린다. 또, 이름이 같은 함수이면 매개변수 타입이 달라도 가린다.
  • 9. Item33. 상속된 이름을 숨기지 말자 이럴 때 using을 사용하여 본래 Base의 함수를 상속받을 수 있다.
  • 10. Item34. 인터페이스 상속과 구현 상속의 차이를 구별하자 • 인터페이스 상속: 함수의 선언 부를 상속 • 구현 상속: 함수의 구현 부를 상속 • 여러 가지 상황에 따라 인터페이스 상속만 필요할 경우가 있고 구현 상속이 필요할 경우도 있다.
  • 11. Item34. 인터페이스 상속과 구현 상속의 차이를 구별하자 Draw()함수가 바로 순수 가상 함수이고, error()는 가상 함수, objectID()는 비가상 함수 이 다.
  • 12. • 순수 가상 함수 • 함수의 인터페이스 만을 물려주려는 것 • Shape::draw처럼 모든 객체는 그리기가 가능해야 하지만 모든 객체의 그리는 알고리즘이 같을 리가 없기 때문 (ex)직사각형 != 타원 Item34. 인터페이스 상속과 구현 상속의 차이를 구별하자
  • 13. • 가상 함수 • 파생 클래스로 하여금 함수의 인터페이스뿐만 아니라 그 함수 의 기본 구현도 물려받게 하는 것 • Shape::error 처럼 기본 인터페이스를 제공 하면서 파생 객체에 서 error가 났을 때 Shape의 기본 error 구현을 가져다 사용 할 수 있게 한다. 만약 기본 클래스의 구현을 사용하고 싶지 않다면 파생 클래스 개별적으로 구현도 가능하다. Item34. 인터페이스 상속과 구현 상속의 차이를 구별하자
  • 14. • 비가상 함수 • Shape::objectID(), 클래스 파생에 상관없이 변하지 않는 동작에 쓰임 • 인터페이스와 그 함수의 필수적인 구현을 상속 • 파생 클래스에서 재정의 불가 Item34. 인터페이스 상속과 구현 상속의 차이를 구별하자
  • 15. • 비가상 함수 인터페이스 (non-virtual-interface: NVI) • Class GameCharacter{ public: int healthValue() const { . . . // 사전 동작 int retVal = doHealthValue(); // privat의 가상함수를 호출 . . . // 사후 동작 return retVal; } private: virtual int doHealthValue() const { . . . } Item35. 가상 함수 대신을 생각해 두자 사용자가 직접 가상함수를 호출 하지 않게 함 으로 써 사전 동작과 사후 동작 사이에서 가 상 함수를 호출 할 수 있게 되었다.
  • 16. Item35. 가상 함수 대신을 생각해 두자 • std::function으로 구현한 전략 패턴 • std::function을 이용하여 함수 포인터 처럼 사용할 수 있다. • HealthCalcFunc을 설정하는 함수를 따로두어 게임 진행 중에도 체력 계산 치를 바꾸어 줄 수 있다.
  • 17. Item35. 가상 함수 대신을 생각해 두자 • 고전적인 전략 패턴 고전적인 전략 패턴으로 HealthCalcFunc 클래스 계통에 파생 클래스를 추가함으로써 기존의 체력치 계산 알고리즘을 조정/개조 할 가능성도 열어 두었다는 점은 플러스 이다.
  • 18. Item36. 상속 받은 비가상 함수를 파생 클래스에서 재정의 X • B로부터 파생된 클래스인 D에서 mf()함수를 재정의 하게 되면 기본 클래스의 mf()함수를 가리게 된다. • 위 처럼 동작하는 이유는 비 가상 함수를 정적 바인딩이기 때문이다.  pB는 B에대한 포인터로 선언 되었기 때문에 비 가상함수mf()가 반드시 B에 존재 할거 라 생각 하는 것이다. • 또 파생클래스인 D에서 mf()를 호출 할 때 B의 mf()로 갈지 D의 mf()로 갈지 난해한 상황
  • 19. Item37. 상속 받은 기본 매개변수 값은 절대 재정의 X
  • 20. Item37. 상속 받은 기본 매개변수 값은 절대 재정의 X pc의 동적타입은 Circle* pr의 동적타입은 Rectangle* 가상 함수는 동적 바인딩 된다. pr의 동적 타입은 Rectangle* 이므로 Rectangle의 draw함수를 불러 오지만 기본 매개변수 는 정적으로 바인딩 되기 때문에 정적 타입인 Shape*의 매개변수를 가져 오는 참사가 발 생하게 된다.
  • 21. • 그래도 매개변수를 건들고 싶다면… 비가상 인터페이스 관용구(NVI)를 사용하자(Item 35)  가상 함수를 private으로 두고 이를 호출하는 비가상 함수를 기본 클래스에 두는 방식 이를 이용하여 비가상 함수가 매개변수를 지정할 수 있게 할 수 있다. Item37. 상속 받은 기본 매개변수 값은 절대 재정의 X
  • 22. • 객체 합성: 어떤 타입의 객체가 다른 타입의 객체들을 포함하고 있는 관계 Item38. has a, is a 모형화할 때 객체합성을 이용하자
  • 23. • 응용 영역: 객체 중 일상생활에서 볼 수 있는 것을 본뜬 것 (ex) 사람, 이동수단 • 구현 영역: 버퍼, 뮤텍스, 탐색트리등 시스템 구현만을 위한 인 공물이 속한 객체 • 객체 합성이 응용 영역에서 일어나면 has-a 관계 구현 영역에서 일어나면 is-implemented-in-terms-of 관계이다. Item38. has a, is a 모형화할 때 객체합성을 이용하자
  • 24. • has- a 관계 전에 보여주었던 Person과 Address의 관계 • is-implemented-in-terms-of 관계가 필요한 예 set 템플릿을 list에서 파생된 형태로 만들고 싶을 때 is-a 관계로 했더니 list의 중복 원소를 가질 수 있는 기본 성질 을 set에서는 적용할 수가 없다. Item38. has a, is a 모형화할 때 객체합성을 이용하자
  • 25. Item38. has a, is a 모형화할 때 객체합성을 이용하자 이러한 상황일 때 is-implemented-in-terms-of 관계를 이용하면 된다.