기초 클래스와 유도 클래스의 가상 함수를 선택적으로 쓰기위한 방법??
메서드를 호출하는 객체의 데이터형에 따라 사용된 메서드가 결정된다.
~cpp
BankAccount bretta; // 기초 클래스 객체
Overdraft ophelia; // 유도 클래스 객체
bretta.ViewAcct (); // BacnkAccount::ViewAcct ()를 사용
ophelia.ViewAcct (); // Oberdraft::ViewAcct ()를 사용
그런데, 포인터를 사용하여 메서드를 호출한다고 가정해보자
~cpp
BankAccount *bp = &bretta; // BackAccount객체를 지시
bp->ViewAcct (); // BackAccount::ViewAcct ()를 사용
bp = &ophelia; // Overdraft 객체를 지시하는 BackAccount 포인터
bp->ViewAcct (); // 헉! 어느 버전을 사용하지?
여기서 컴파일러가 포인터형을 사용한다면 마지막 명령문은
BackAccount::ViewAcct ()를 호출하겠지만 포인터가 지시하는 객체의 데이터 형을 사용한다면
Overdraft::ViewAcct ()를 호출할 것이다. 그렇다면 컴파일러는 어떤 선택을 할것인가?
기본적으로 C++는 포인터나 참조의 데이터형을 사용하여 사용할 함수를 결정하고 지시되거나 참조된 대상 객체의 데이터형을 무시한다. 그러므로 앞의 예에서 프로그램은
BackAccount::ViewAcct ()를 사용할 것이다. 이렇게 하는 이유는 분명하다. 컴파일러가 데이터형을 모르는 경우가 많기 때문이다. 예를 들어..
~cpp
int nSelect;
cin >> nSelect;
BackAccount *bp;
if (nSelect == 1)
bp = new BackAccount;
else if (nSelect == 2)
bp = new Overdraft;
bp->ViewAcct ();
컴파일러는 컴파일할 때에는 실행 시간에 어떤 항목이 선택될지를 알 수 없으므로 bp가 지시하는 객체의 데이터형을 알 수 없다. 따라서 컴파일러가 컴파일할 때 할 수 있는 일은 클래스 메서드를 참조나 포인터의 데이터 형에 일치시키는 것뿐이다. 이 경우를 early binding 또는 static binding이라 한다.
~cpp
// 정적 결합 사용
bp = &ophelia; // Overdraft객체를 지시하는 BackAccount포인터
bp->ViewAcct (); // BackAccount::ViewAcct ()를 사용
Overdraft 객체에
BackAccount::ViewAcct ()를 사용해도 문제될 것은 없고 다만 일부 테이터가 출력되지 않을 뿐이다. 그렇다면 bp->
ViewAcct ()를 포인터형 객체형에 결합하여
Overdraft::ViewAcct ()를 호출할 수 있으면 좋을 것이다. C++는 이 목표를 달성하기 위해 late binding 또는 dynamic binding이라는 것을 제공한다. 이 것에서는 컴파일러가 사용할 클래스 메서드를 결정하지 않고 프로그램 실행 시간에 메서드 함수 호출을 실제로 수행할 때마다 사용할 클래스 메서드를 결정하게 한다. 이 것을 사용하면 참조나 포인터가 지시하는 객체의 형에 따라 메서드를 선택할 수 있다.
~cpp
// 동적 결합
BackAccount *bp = &bretta;
bp->ViewAcct (); // BackAccount::ViewAcct ()를 사용
bp = &ophelia;
bp->ViewAcct (); // Overdraft::ViewAcct ()를 사용