효과적인 C ++ 절 37 : 상속과 객체 지향 합 (상속의 기본 매개 변수 값을 재정의하지 않음)

머리말

  • 상속 계층에 도입 점에서 (36), 유도 클래스 바람직 닫기 만이 아닌 가상베이스 클래스로 이동하지 않고 가상 함수를 오버라이드 커버
  • 따라서, 소개하는이 절은 "기본 매개 변수 값이 상속 재정의하지 않음" 의 관점에서 가상 함수입니다
  • 중요한 개념 : 가상 함수는 동적으로 바인딩되지만, 기본 매개 변수 값 가상 함수는 정적 바인딩

첫째, 정적 유형 및 동적 유형

  • 정적 유형 : 에 의해 채택 된 선언의 유형
  • 동적 유형 : 현재의 지식 객체 유형

사례 발표

  • 다음은 상속 계층 구조입니다
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 = 0;
};

class Circle :public Shape {
public:
    virtual void draw(ShapeColor color)const = 0;
};

  • 이제 우리는 다음과 같은 코드를 정의, 그들은 그들이 가리 상관없이 그래서, 정적 형식은 모양입니다 *, 핀터 - 투 - Shpae 유형으로 선언된다 :
Shape* ps;                 //静态类型为Shape*
Shape* pc = new Circle;    //静态类型为Shape*
Shape* pr = new Rectangle; //静态类型为Shape*
  • 어떤 행동이있을 것이다 오브젝트 수단의 동적 유형입니다. 예를 들면 :
Shape* ps;
Shape* pc = new Circle;
Shape* pr = new Rectangle;

ps = pc; //ps的动态类型如今是Circle*
ps = pr; //ps的动态类型如今是Rectangle*
  • 우리는 가상 함수를 호출하는 구문에 따라 동적 유형에 따라 결정된다는 것을 알고있다. 예를 들면 :
Shape* ps;                 
Shape* pc = new Circle; 
Shape* pr = new Rectangle;

pc->draw(Shape::Red); //调用Circle::draw(Shape::Red)
pr->draw(Shape::Red); //调用Rectangle::draw(Shape::Red)

둘째, 기본 매개 변수는 가상 함수는 정적 바인딩 값

  • 가상 기능에 대한 가상 동적 바인딩 기능을하지만, 기본 매개 변수 값을 호출하는 시간은 정적으로 바인딩되어 있지만
  • 다음 코드를 참조하십시오 :
    • 우리는 가상 함수는 동적 바인딩 것을 알고있다 () 호출이 직사각형 :: 그릴 그래서, 홍보 사각형의 동적 유형을
    • 그러나 가상 기본 매개 변수 값을 정적 바인딩 기능이다 매개 변수없이 위의 클래스 무승부의 정의에서 사각형 () 함수,하지만 인해 모양 포인터 홍보 정적 유형, 추첨 () 함수의 기본 매개 변수 값 때문에 그것은 모양에 대한 매개 변수 값의 형태 :: 무승부 () 함수 :: 레드
Shape* pr = new Rectangle;
pr->draw(); //调用的是Rectangle::draw(Shape::Red)


//Circle也是相同的道理
Shape* pc = new Circle;
pc->draw(); //调用的是Circle::draw(Shape::Red),而不是Circle::draw(Shape::Green)
  • 왜이 동작을 설계 : 운영 효율성이. 기본 매개 변수 값이 동적 바인딩 경우, 컴파일러는 현재 위치에 느린 더 복잡한 "컴파일 타임에 결정에서"메커니즘보다 런타임에 가상 함수에 해당하는 매개 변수의 기본 값을 확인 할 수있는 방법이어야합니다

셋째, 상속의 기본 매개 변수 값을 다시 정의하지 않습니다

  • 둘째, 우리는 알고 기본 매개 변수는 가상 함수는 정적 바인딩 값. 가상 함수를 호출 할 때 예기치 않은 결과 때문에 따라서, 우리는 기본 매개 변수 값이 상속 재정의하지 않습니다 (코드는 PC로 무승부를 (호출 이상은) 예입니다)

주어진 넷째, 기본 매개 변수 값 가상 함수의 권장 사항에 대한 응답,

비효율적 인 프로그램보기

  • 기본 클래스 일관성 파생 클래스 및하는 비효율적 인 방법으로 가상 함수 일관성 디폴트 파라미터 값을 설정하고 기본 클래스 유래
  • 예를 들면 :
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 = Red)const;
};

class Circle :public Shape {
public:
    virtual void draw(ShapeColor color = Red)const;
};
  • 비효율적 인 이유 :
    • ① 코드 중복
    • ② 의존은 기본 클래스의 기본 매개 변수 값이 변경된 경우, 당신은 다시 수정 된 기본 매개 변수 값 파생 클래스가 필요, 너무 높은

클래스를 정의하는 NVI는 방법

  • 항목 36 피하기 기본 매개 변수의 기본 클래스에 순서대로 소개합니다 기본 매개 변수 값 virutal 기능에 대한 NVI 기술 및 파생 클래스의 값은 우리가이 방법을 취할 수, 일치하지 않는
  • 코드를 다음과 같이 정의된다 :
class Shape {
public:
    enum ShapeColor { Red, Green, Blue };
    void draw(ShapeColor color = Red)const { //因为是non-virtual函数,因此不建议派生类隐藏
        doDraw(Red);
    }
private:
    //真正的工作在此处完成,派生类可以重写
    virtual void doDraw(ShapeColor color)const = 0;
};


class Rectangle :public Shape {
private:
    virtual void doDraw(ShapeColor color)const = 0;
};
  • doDraw 위 () 함수는 실제 함수를 완료하고 유형 ShapeColor을 허용하는
  • 우리는 레드에 그것의 매개 변수 기본값이 아닌 가상 함수 무승부를 정의하고, 비 가상 함수 때문에, 숨기기에 파생 클래스를 권장하지 않습니다 () 기본값이 매개 변수는 항상 레드 것, 기능이 기본 클래스 또는 파생 클래스가 무승부를 호출 여부 우리의 궁극적 인 목표를 달성하기 위해

V. 요약

  • 당신이 커버해야 할 유일한 것은 - - 그것은 동적 바인딩은 절대로 기본 매개 변수 값을 정적 바인딩 및 virutal 기능이기 때문에, 상속의 기본 매개 변수 값을 재정의하지
发布了1525 篇原创文章 · 获赞 1085 · 访问量 45万+

추천

출처blog.csdn.net/qq_41453285/article/details/104818312