C++다 태 성과 허 함 수 를 깊이 있 게 분석 하 다

한 가지 유형 을 파생 시 키 는 이 유 는 항상 새로운 구성원 을 계승 하거나 추가 하기 위 한 것 이 아니 라,때로는 기본 적 인 구성원 을 새롭게 정의 하여 기본 적 인 구성원 을'신입생'으로 만 들 기 위 한 것 이다.대상 을 대상 으로 하 는 프로 그래 밍 의 진정한 힘 은 계승 뿐만 아니 라 파생 대상 이 기본 대상 처럼 처리 하도록 허용 하 는 데 있다.그 핵심 체 제 는 다 형 과 동적 연결 이다.
(1)다 태 성
다 태 는 같은 소식 이 서로 다른 대상 에 게 접 수 될 때 서로 다른 행 위 를 초래 하 는 것 을 말한다.메시지 란 클래스 구성원 함수 에 대한 호출 을 말 하 는데 서로 다른 행 위 는 서로 다른 실현,즉 서로 다른 함 수 를 호출 하 는 것 을 말한다.
1)다 태 적 분류
넓 은 의미 에서 다 형 성 은 프로그램 이 다양한 유형의 대상 을 처리 할 수 있 는 능력 을 말한다.C++에서 이러한 다 형 성 은 다 형(함수 와 연산 자 를 다시 불 러 오기)을 통 해 강제로 다시 불 러 오기(유형 강제 변환),유형 매개 변수 화 다 형(템 플 릿)을 사용 할 수 있 습 니 다.
다 중(계승 과 허 함수)네 가지 방식 으로 이 루어 집 니 다.유형 매개 변수 화 다 형 과 다 형 을 포함 하 는 것 을 일반 다 형 성 이 라 고 부 르 며 의미 와 관련 된 유형 을 체계적으로 묘사 하 는 데 사용 된다.과부하 다 형 과 강제 다 형 성 을 특수 다 형 성 이 라 고 부 르 며 의미 적 으로 관련 이 없 는 유형 간 의 관 계 를 묘사 하 는 데 사용 된다.
C++에서 가상 함 수 를 사용 하여 다 중 을 포함 합 니 다.가상 함 수 는 C++에 더욱 유연 한 다 중 체 제 를 제공 합 니 다.이러한 다 형 성 은 프로그램 이 실 행 될 때 만 확인 할 수 있 습 니 다.따라서 가상 함 수 는 다 형 적 인 정수 이 고 적어도 하나의 가상 함 수 를 포함 한 클래스 를 다 형 류 라 고 합 니 다.대상 을 대상 으로 하 는 프로그램 설계 에 다 중 태 를 포함 하 는 것 이 빈번 하 다.
2)정적 연결
연결 은 바 인 딩 이 라 고도 부 릅 니 다.모듈 이나 함 수 를 합 쳐 실행 가능 한 코드 를 만 드 는 처리 과정 입 니 다.또한 각 모듈 이나 함수 에 메모리 주 소 를 할당 하고 외부 방문 에 도 정확 한 메모리 주 소 를 제공 합 니 다.
컴 파일 단계 에서 함 수 를 함수 호출 과 연결 시 키 는 것 을 정적 연결 이 라 고 합 니 다.정적 연결 은 컴 파일 단계 에서 모든 함수 와 모듈 실행 에 필요 한 정 보 를 알 아야 합 니 다.함수 에 대한 선택 은 대상 을 가리 키 는 포인터(또는 참조)형식 을 기반 으로 합 니 다.C 언어 에서 모든 연결 은 정적 연결 입 니 다.C++의 일반적인 상황 도 정적 연결 입 니 다.

class Point{
  public:
    void area(){cout<<"point";}
  };
  class Circle:public Point{
  public:
    void area(){cout<<"circle";}
  };
  Point a; Circle c;
  a.area();   //  a.Point::area() 
  c.area();   //  c.Circle::area(),      
  Point * pc=&c,&rc=c;  //            
  pc->area();  //  pc->Point::area()
  rc.area();   //  rc.Point::area()
3)동적 연결
프로그램 이 실 행 될 때 만 함수 구현 과 함수 호출 의 바 인 딩 을 동적 연결 이 라 고 합 니 다.위의 예 를 들 어 컴 파일 할 때 호환성 규칙 에 따라 합 리 성 을 검사 하면 파생 류 대상 주소 가 기본 포인터 변수 에 할당 할 수 있 는 조건 에 부합 되 는 지 확인 하 는 것 입 니 다.pc->area()에서 어떤 함 수 를 호출 할 지 는 프로그램 이 여기까지 실 행 될 때 까지 기 다 려 야 결정 합 니 다.Circle::area()를 호출 하려 면 Point 류 의 area()함 수 를 가상 함수 로 지정 해 야 합 니 다.정의 형식:
   virtual void area(){cout<<"point";}컴 파일 러 가 가상 함 수 를 포함 하 는 클래스 를 컴 파일 할 때 그 에 게 가상 함수 표 VTABLE 를 만들어 줄 것 입 니 다.이것 은 포인터 배열 에 해당 하고 모든 가상 함수 의 입구 주 소 를 저장 합 니 다.컴 파일 러 는 이러한 종류의 추가 데이터 구성원 을 증감 합 니 다.이 데이터 구성원 은 가상 함수 표를 가리 키 는 지침 으로 vptr 라 고 합 니 다.
파생 류 가 이 가상 함 수 를 다시 쓰 지 않 으 면 파생 류 의 가상 함수 목록 에서 요소 가 가리 키 는 주 소 는 기본 함수 area()의 주소 입 니 다.즉,파생 류 는 기본 클래스 의 가상 함수 만 계승 하 는 것 입 니 다.
파생 클래스 가 이 허 함 수 를 다시 쓰 면 다음 과 같 습 니 다.
   virtual void area() {cout<<"circle";}그러면 이 때 컴 파일 러 는 파생 클래스 허 함수 표 의 요 소 를 Circle:area()로 가리 킵 니 다.
컴 파일 러 는 가상 함 수 를 포함 하 는 대상 에 게 먼저 함수 입구 주 소 를 만 듭 니 다.이 주 소 는 가상 함수 표를 가리 키 는 포인터 vptr 를 저장 한 다음 에 클래스 의 가상 함수 성명 순서에 따라 함수 지침 을 일일이 입력 합 니 다.가상 함 수 를 호출 할 때 먼저 vptr 를 통 해 가상 함수 표를 찾 은 다음 에 가상 함수 의 진정한 주 소 를 찾 습 니 다.
파생 류 는 기본 클래스 의 가상 함수 표를 계승 할 수 있 으 며,기본 클래스 와 같은 이름(매개 변수 도 같 음)의 구성원 함수 라면 가상 성명 을 사용 하 든 말 든 자동 으로 가상 함 수 를 생 성 합 니 다.파생 류 가 계승 기본 클래스 의 허 함 수 를 바 꾸 지 않 으 면 함수 포인터 가 기본 클래스 의 허 함 수 를 호출 합 니 다. 
(2)가상 함수
1)가상 함수 정의
가상 함 수 는 클래스 의 한 구성원 함수 일 뿐 정적 일 수 없습니다.구성원 함수 정의 나 성명 전에 키워드 virtual 을 추가 하면 가상 함 수 를 정의 합 니 다.

class  {
    ...
    virtual          (      )//   
    ...
  };
  class Point
  {
    virtual void area ();    //     
    virtual double volumn(){}  //      
  };
virtual 키 워드 는 클래스 에서 만 사용 되 는 것 을 주의해 야 합 니 다.
가상 함 수 를 이용 하여 기본 클래스 와 파생 클래스 에서 같은 함수 명 정의 함수 가 서로 다른 실현 을 사용 하여'하나의 인터페이스,다양한 방식'을 실현 할 수 있 습 니 다.기본 포인터 나 참조 가 가상 함수 에 접근 할 때 시스템 은 실행 시 포인터 나 참조 하 는 실제 대상 에 따라 호출 대상 이 있 는 가상 함수 버 전 을 자동 으로 확인 합 니 다.
2)가상 함수 다 중 조건 실현
키워드 virtual 지시 C++컴 파일 러 는 가상 함 수 를 동적 으로 연결 합 니 다.이런 다 태 성 은 프로그램 이 상응하는 문장 에 실행 되 어야 동태 적 으로 확 정 된 것 으로 운행 시의 다 태 성 이 라 고 한다.그러나 허 함 수 를 사용 하면 반드시 다 태 성 이 생기 는 것 도 아니 고 동적 연결 을 사용 하 는 것 도 아니다.예 를 들 어 호출 에서 가상 함수 에 대한 구성원 이름 제한 을 사용 하면 C++이 함수 에 대한 호출 을 정적 연결 로 강제 할 수 있 습 니 다.
가상 함수 가 실 행 될 때의 다 태 성 은 반드시 두 가지 조건 이 있어 야 한다.
a)파생 류 는 동명 의 허 함 수 를 고 쳤 다.
b)할당 호환성 규칙 에 따라 포인터 또는 참조 사용

Point *p=new Circle;  //         
  cout<<p->area();   //    
  void fun(Point *p)
  {cout<<p->area();}   //    
3)파생 클래스 에서 기본 구성원 함 수 를 가리 키 는 지침 이 가상 함 수 를 가리 키 고 대상 을 가리 키 는 지침 이나 인용 을 통 해 이 가상 함 수 를 방문 할 때 다 형 성 이 발생 합 니 다.

#include<iostream>
using namespace std;
class Base{
public: virtual void print(){cout<<"base"<<endl;}
};

class Derived :public Base{
public:
 void print(){cout<<"derive"<<endl;}
};

//void(Base::*pf)();
void display(Base *p,void(Base::*pf)())
{
(p->*pf)();

}

int main()
{
 Derived d;
 Base b;
 display(&d,&Base::print);
 display(&b,&Base::print);
 return 0;
}

lzb@lzb:~/classic_lib/C++_learning$ g++ 427.cpp
lzb@lzb:~/classic_lib/C++_learning$ ./a.out 
derive
base
display 에는 두 개의 함수 가 있 습 니 다.첫 번 째 매개 변 수 는 기본 포인터 이 고 두 번 째 매개 변 수 는 클래스 구성원 함 수 를 가리 키 는 지침 입 니 다.display 는 기본 포인터 로 구성원 함 수 를 가리 키 는 포인터 가 가리 키 는 구성원 함 수 를 호출 합 니 다.기본 클래스 의 가상 함 수 를 호출 하 느 냐,파생 클래스 의 가상 함 수 를 호출 하 느 냐 는 기본 포인터 가 가리 키 는 대상 에 달 려 있다. 
보충:
대상 을 대상 으로 하 는 세 가지 특징:포장,계승 과 다 형.
무엇이 다 형 입 니까?
다 태 적 의 미 는 한 사물 에 여러 가지 형태 가 있 는데 영어 단 어 는 polymorphism 으로 서로 다른 대상 에 게 같은 메 시 지 를 보 내 고 서로 다른 대상 이 받 을 때 서로 다른 행동(방법)을 하 게 된다 는 것 이다.대상 마다 공 통 된 소식 을 자신의 방식 으로 전달 할 수 있다 는 것 이다.
예 를 들 어 함수 의 과부하,연산 자의 과부하 는 모두 다 중 현상 이다.
한 생활 속 의 예,예 를 들 어 학생 이 개학 할 때 교장 이 어느 날 개학 하 는 지 에 대한 정 보 를 발표 하면 서로 다른 대상 이 서로 다른 반응 을 보일 것 이다.학생 들 은 학 교 를 준비 해 야 한다.학부 모 는 학 비 를 준비 해 야 하고 선생님 도 수업 준 비 를 시작 해 야 한다.학교 식당 에서 식재 료 를 구 매 하기 시작 하 는 것 이 다 형 성 이다.다 형 성 이 없 으 면 교장 은 각각 학생,교사 와 학부 모 등 서로 다른 대상 은 따로 통 지 를 보낸다.
C++에서 다 형 적 표현 형식 중 하 나 는 서로 다른 기능 을 가 진 함수 가 같은 함수 명 을 사용 할 수 있다 는 것 이다.그러면 하나의 함수 명 으로 서로 다른 내용 을 호출 하 는 함 수 를 실현 할 수 있다.
시스템 실현 의 측면 에서 볼 때 다 형 성 은 두 가지 로 나 뉜 다.정 다 형 성과 동 다 형 성 이다.
정적 다 태 성 은 함수 재 부팅 을 통 해 이 루어 지고 동적 다 태 성 은 가상 함 수 를 통 해 이 루어 진다.
뭐 공부 해요?
C++의 가상 함 수 는 동적 다 중 문 제 를 해결 하 는 데 사 용 됩 니 다.이른바 가상 함수 란 기본 적 인 성명 함수 가 가상 이 고 실제 존재 하 는 것 이 아 닙 니 다.그리고 파생 류 에서 이 함 수 를 정식 적 으로 정의 합 니 다.프로그램 이 실행 되 는 동안 특정한 파생 류 대상 을 지침 으로 가리 키 면 지침 이 가리 키 는 파생 류 대상 중의 함 수 를 호출 할 수 있 습 니 다.다른 파생 클래스 의 함 수 를 호출 하지 않 습 니 다.
총결산
이상 에서 말 한 것 은 소 편 이 여러분 에 게 소개 한 C++다 태 성과 허 함수 입 니 다.여러분 에 게 도움 이 되 기 를 바 랍 니 다!

좋은 웹페이지 즐겨찾기