일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
Tags
- 예외
- Effective c++
- effective stl
- 반복자
- 상속
- 참조자
- std::async
- effective modern c++
- iterator
- more effective c++
- exception
- operator new
- 오블완
- reference
- resource management class
- 보편 참조
- virtual function
- 영화
- 암시적 변환
- universal reference
- UE4
- lua
- 영화 리뷰
- Smart Pointer
- c++
- implicit conversion
- 게임
- 티스토리챌린지
- 스마트 포인터
- 언리얼
Archives
- Today
- Total
스토리텔링 개발자
[Effective C++] 37. 상속된 함수의 매개변수 기본값 재정의 문제 본문
728x90
항목 37. 어떤 함수에 대해서도 상속받은 기본 매개변수 값은 절대로 재정의하지 말자
기본 매개변수 값을 재정의할 시 문제 상황
class Shape
{
public:
enum ShapeColor { Red, Green, Blue };
virtual void draw(ShapeColor color = Red) const = 0;
...
};
class Rectangle : public Shape
{
public:
virtual void draw(ShapeColor color = Green) const; // 기본 매개변수 재정의!!!
...
};
Shape* ps;
Shape* pr = new Rectangle;
pr->darw(); // Rectangle::draw(Shape::Red)를 호출한다!!!!
- 호출 함수의 경우 동적 타입에서 가져오지만, 매개변수의 경우 정적 타입에서 가져온다.
- 즉, 기본 매개변수 재정의가 되어있는 경우, 정적 타입에 따라 기본 매개변수가 마구 변경되기에 동작을 예측하기 쉽지 않다!
정적 타입과 동적 타입
- 정적 타입(static type)
- 선언문을 통해 그 객체가 갖는 타입.
- 동적 타입(dynamic type)
- 현재 그 객체가 진짜로 무엇이냐에 따라 결정되는 타입.
Shape* pr = new Rectangle;
// 정적 타입 : Shape
// 동적 타입 : Rectangle
C++이 이런 방식을 고집하는 이유
- 런타임 효율 문제
- 기본 매개변수가 동적으로 바인딩된다면?
- 런타임 중 가상함수의 기본 매개변수 값을 결정할 방법을 컴파일러 쪽에서 마련해야 한다.
- 이는 현재 메커니즘보다 느리고 복잡할 것이 분명하다.
- 기본 매개변수를 사용하는 경우가 한정적이므로 효율을 선택했을 것이다.
- 기본 매개변수가 동적으로 바인딩된다면?
파생 클래스가 기본 매개변수 값을 똑같이 제공한다면?
class Shape
{
public:
virtual void draw(ShapeColor color = Red) const = 0;
...
};
class Rectangle : public Shape
{
public:
virtual void draw(ShapeColor color = Red) const;
...
};
- 문제점
- 코드 중복이며, 의존성까지 걸려있다.
- 부모 클래스 draw의 기본 매개변수를 변경한다면?
- 상속받은 기본 매개변수 값을 재정의하는 꼴이나 마찬가지가 되므로 파생 클래스 쪽도 손봐줘야 한다.
- 코드 중복이며, 의존성까지 걸려있다.
해결 방법
- 가상 함수 대신 사용할 수 있는 방법들을 활용하자.(항목 35 참조)
- 비가상 인터페이스 관용구(NVI 관용구)를 사용해 보자.
class Shape
{
public:
// 비가상 함수에 기본 매개변수 처리
void draw(ShapeColor color = Red) const
{
// 가상 함수 호출
doDraw(color);
}
...
private:
virtual void doDraw(ShapeColor color) const = 0;
};
class Rectangle : public Shape
{
public:
...
private:
virtual void doDraw(ShapeColor color) const;
...
};
728x90
'Effective C++ > Effective C++' 카테고리의 다른 글
[Effective C++] 39. private 상속 (0) | 2024.07.09 |
---|---|
[Effective C++] 38. 객체 합성 (0) | 2024.07.08 |
[Effective C++] 36. 상속된 비가상 함수 이름 가리기 문제 (0) | 2024.07.05 |
[Effective C++] 35. 일반 가상 함수 외의 구현법 (0) | 2024.07.04 |
[Effective C++] 34. 인터페이스 상속과 구현 상속의 차이 (0) | 2024.07.03 |
Comments