가상 함수
가상 함수는 파생 된 클래스에서 다시 정의 될 것으로 예상 되는 함수가입니다.파생된 클래스에 대 한 포인터 또는 참조를 기본 클래스를 사용 하 여 개체를 참조할 때 해당 개체에 대 한 가상 함수를 호출 하 고 파생된 클래스의 버전의 함수를 실행 있습니다.
가상 함수가 함수를 호출 하는 데 사용 되는 식에 관계 없이 개체에 대해 올바른 함수를 호출 해야 합니다.
기본 클래스 이름으로 선언 된 함수를 포함 하는 가정 가상 와 같은 함수는 파생된 클래스를 정의 합니다.포인터 또는 참조를 기본 클래스를 사용 하 여 호출 되는 경우에 함수에서 파생 된 클래스는 파생된 클래스의 개체에 대해 호출 됩니다.다음 예제에서 구현을 제공 하는 기본 클래스의 PrintBalance 파생 된 두 클래스 및 함수
// deriv_VirtualFunctions.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;
class Account {
public:
Account( double d ) { _balance = d; }
virtual double GetBalance() { return _balance; }
virtual void PrintBalance() { cerr << "Error. Balance not available for base type." << endl; }
private:
double _balance;
};
class CheckingAccount : public Account {
public:
CheckingAccount(double d) : Account(d) {}
void PrintBalance() { cout << "Checking account balance: " << GetBalance() << endl; }
};
class SavingsAccount : public Account {
public:
SavingsAccount(double d) : Account(d) {}
void PrintBalance() { cout << "Savings account balance: " << GetBalance(); }
};
int main() {
// Create objects of type CheckingAccount and SavingsAccount.
CheckingAccount *pChecking = new CheckingAccount( 100.00 ) ;
SavingsAccount *pSavings = new SavingsAccount( 1000.00 );
// Call PrintBalance using a pointer to Account.
Account *pAccount = pChecking;
pAccount->PrintBalance();
// Call PrintBalance using a pointer to Account.
pAccount = pSavings;
pAccount->PrintBalance();
}
앞의 코드에서 호출을 PrintBalance 개체를 제외 하 고 동일 합니다. pAccount 를 가리킵니다.때문에 PrintBalance 가상,이 버전의 호출 각 개체에 대해 정의 된 함수입니다.PrintBalance 파생된 클래스의 함수 CheckingAccount 및 SavingsAccount "기본 클래스에서 함수를 재정의" Account.
재정의 구현을 제공 하지 않습니다는 클래스를 선언 하는 경우는 PrintBalance 함수, 기본 클래스의 기본 구현은 Account 사용 됩니다.
형식 같은 경우에 파생된 클래스의 함수에서 기본 클래스 가상 함수를 재정의 합니다.파생된 클래스의 가상 함수에만 반환 형식이 기본 클래스의 다 수 없습니다. 인수 목록도 달라 야 합니다.
포인터나 참조를 사용 하 여 함수를 호출할 때는 다음과 같은 규칙이 적용 됩니다.
가상 함수를 호출 하는 호출 개체의 내부 형식에 따라 확인 됩니다.
비가상 함수를 호출 하는 포인터 또는 참조 형식에 따라 확인 됩니다.
다음 예제는 가상 메서드와 비가상 함수 포인터를 통해 호출할 때 작동 합니다.
// deriv_VirtualFunctions2.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;
class Base {
public:
virtual void NameOf(); // Virtual function.
void InvokingClass(); // Nonvirtual function.
};
// Implement the two functions.
void Base::NameOf() {
cout << "Base::NameOf\n";
}
void Base::InvokingClass() {
cout << "Invoked by Base\n";
}
class Derived : public Base {
public:
void NameOf(); // Virtual function.
void InvokingClass(); // Nonvirtual function.
};
// Implement the two functions.
void Derived::NameOf() {
cout << "Derived::NameOf\n";
}
void Derived::InvokingClass() {
cout << "Invoked by Derived\n";
}
int main() {
// Declare an object of type Derived.
Derived aDerived;
// Declare two pointers, one of type Derived * and the other
// of type Base *, and initialize them to point to aDerived.
Derived *pDerived = &aDerived;
Base *pBase = &aDerived;
// Call the functions.
pBase->NameOf(); // Call virtual function.
pBase->InvokingClass(); // Call nonvirtual function.
pDerived->NameOf(); // Call virtual function.
pDerived->InvokingClass(); // Call nonvirtual function.
}
Output
Derived::NameOf
Invoked by Base
Derived::NameOf
Invoked by Derived
여부에 관계 없이 참고는 NameOf 에 대 한 포인터를 통해 함수를 호출할 Base 또는 포인터 Derived, 호출 하는 함수에 대 한 Derived.호출 하는 함수에 대 한 Derived 때문에 NameOf 가상 함수를 사용 하 고 둘 다 pBase 및 pDerived 형식의 개체를 가리키고 Derived.
클래스 형식 개체에 대 한 가상 함수를 호출 하기 때문에 전역 또는 정적 함수를 선언할 수 없습니다 가상.
해당 가상 키워드는 파생 클래스에서 재정의 하는 함수를 선언할 때 사용 될 수 있지만 필요 합니다. 재정의 가상 함수는 항상 가상 됩니다.
사용 하 여 선언 되지 않은 경우 기본 클래스의 가상 함수를 정의 해야 합니다의 순수 지정자.(순수 가상 함수에 대 한 자세한 내용은 추상 클래스입니다.)
가상 함수 호출 메커니즘 범위 결정 연산자를 사용 하 여 함수 이름을 명시적으로 정하여 되지 않을 수 있습니다 (::).이전 하는 것과 관련 된 고려는 Account 클래스입니다.호출 하려면 PrintBalance 기본 클래스에는 다음과 같은 코드를 사용 합니다.
CheckingAccount *pChecking = new CheckingAccount( 100.00 );
pChecking->Account::PrintBalance(); // Explicit qualification.
Account *pAccount = pChecking; // Call Account::PrintBalance
pAccount->Account::PrintBalance(); // Explicit qualification.
두 호출을 PrintBalance 앞의 예제에서 가상 함수 호출 메커니즘을 표시 하지 않습니다.