KoreanFoodie's Study
Effective C++ | 항목 37 : 어떤 함수에 대해서도 상속받은 기본 매개변수 값은 절대로 재정의하지 말자 본문
Tutorials/C++ : Advanced
Effective C++ | 항목 37 : 어떤 함수에 대해서도 상속받은 기본 매개변수 값은 절대로 재정의하지 말자
GoldGiver 2022. 10. 25. 16:28
C++ 프로그래머의 필독서이자 바이블인, 스콧 마이어스의 Modern Effective C++ 를 읽고 기억할 내용을 요약하고 있습니다. 꼭 읽어보시길 추천드립니다!
항목 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;
};
class Circle: public Shape
{
public:
virtual void draw(ShapeColor color) const;
};
int main()
{
Shape *ps;
Shape *pc = new Circle;
Shape *pr = new Rectangle;
// Rectangle::draw(Shape::Red) 를 호출!
// Rectangle::draw(Shape::Green) 이 아니다!
pr->draw();
}
위에서, pr->draw() 가 우리가 기대한 대로 동작하지 않는 원인이 뭘까? 호출되는 가상 함수는 Rectangle 것이 맞지만, pr 의 정적 타입은 Shape* 이기 때문에, 가상 함수에 쓰이는 기본 매개변수 값은 Shape 클래스에서 가져온다! 만약 상속받은 가상 함수의 기본 매개변수 값을 재정의하면 위처럼 기상천외한 동작이 발생하는 것이다.
이는, C++ 가 런타임 효율을 위해 기본 매개변수 값을 정적으로 바인딩하기 때문이다.
그렇다면 파생 클래스에서 가상 함수의 기본 매개변수 값을 어떻게 하면 깔끔하게 받게 만들 수 있을까? 여러 방법이 있지만, 비가상 인터페이스(non-virtual interface) 관용구를 사용하는 것을 추천한다. 예시를 보자.
class Shape
{
public:
enum ShapeColor { Red, Green, Blue };
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 { ... }
};
'Tutorials > C++ : Advanced' 카테고리의 다른 글
Comments