Fungsi Virtual
Fungsi virtual adalah fungsi anggota yang Anda harapkan untuk ditentukan ulang dalam kelas turunan. Saat Anda merujuk ke objek kelas turunan menggunakan penunjuk atau referensi ke kelas dasar, Anda dapat memanggil fungsi virtual untuk objek tersebut dan menjalankan versi fungsi kelas turunan.
Fungsi virtual memastikan bahwa fungsi yang benar dipanggil untuk objek, terlepas dari ekspresi yang digunakan untuk melakukan panggilan fungsi.
Misalkan kelas dasar berisi fungsi yang dideklarasikan sebagai virtual dan kelas turunan mendefinisikan fungsi yang sama. Fungsi dari kelas turunan dipanggil untuk objek kelas turunan, bahkan jika dipanggil menggunakan pointer atau referensi ke kelas dasar. Contoh berikut menunjukkan kelas dasar yang menyediakan implementasi PrintBalance
fungsi dan dua kelas turunan
// deriv_VirtualFunctions.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;
class Account {
public:
Account( double d ) { _balance = d; }
virtual ~Account() {}
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 checking( 100.00 );
SavingsAccount savings( 1000.00 );
// Call PrintBalance using a pointer to Account.
Account *pAccount = &checking;
pAccount->PrintBalance();
// Call PrintBalance using a pointer to Account.
pAccount = &savings;
pAccount->PrintBalance();
}
Dalam kode sebelumnya, panggilan ke PrintBalance
identik, kecuali untuk titik objek pAccount
. Karena PrintBalance
virtual, versi fungsi yang ditentukan untuk setiap objek dipanggil. Fungsi PrintBalance
dalam kelas CheckingAccount
turunan dan SavingsAccount
"mengambil alih" fungsi di kelas Account
dasar .
Jika kelas dinyatakan tidak memberikan implementasi penggantian PrintBalance
fungsi, implementasi default dari kelas Account
dasar digunakan.
Fungsi dalam kelas turunan mengambil alih fungsi virtual di kelas dasar hanya jika jenisnya sama. Fungsi dalam kelas turunan tidak dapat berbeda dari fungsi virtual di kelas dasar hanya dalam jenis pengembaliannya; daftar argumen juga harus berbeda.
Saat memanggil fungsi menggunakan pointer atau referensi, aturan berikut berlaku:
Panggilan ke fungsi virtual diselesaikan sesuai dengan jenis objek yang mendasar yang dipanggilnya.
Panggilan ke fungsi nonvirtual diselesaikan sesuai dengan jenis penunjuk atau referensi.
Contoh berikut menunjukkan perilaku fungsi virtual dan nonvirtual saat dipanggil melalui penunjuk:
// 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.
}
Derived::NameOf
Invoked by Base
Derived::NameOf
Invoked by Derived
Perhatikan bahwa terlepas dari apakah NameOf
fungsi dipanggil melalui penunjuk ke Base
atau penunjuk ke Derived
, fungsi memanggil fungsi untuk Derived
. Ini memanggil fungsi karena Derived
NameOf
merupakan fungsi virtual, dan keduanya pBase
dan pDerived
menunjuk ke objek jenis Derived
.
Karena fungsi virtual hanya dipanggil untuk objek jenis kelas, Anda tidak dapat mendeklarasikan fungsi global atau statis sebagai virtual
.
Kata virtual
kunci dapat digunakan saat mendeklarasikan fungsi penggantian di kelas turunan, tetapi tidak perlu; penimpaan fungsi virtual selalu virtual.
Fungsi virtual dalam kelas dasar harus didefinisikan kecuali dinyatakan menggunakan penentu murni. (Untuk informasi selengkapnya tentang fungsi virtual murni, lihat Kelas Abstrak.)
Mekanisme panggilan fungsi virtual dapat ditekan dengan secara eksplisit memenuhi syarat nama fungsi menggunakan operator resolusi cakupan (::
). Pertimbangkan contoh sebelumnya yang melibatkan Account
kelas . Untuk memanggil PrintBalance
di kelas dasar, gunakan kode seperti berikut:
CheckingAccount *pChecking = new CheckingAccount( 100.00 );
pChecking->Account::PrintBalance(); // Explicit qualification.
Account *pAccount = pChecking; // Call Account::PrintBalance
pAccount->Account::PrintBalance(); // Explicit qualification.
Kedua panggilan ke PrintBalance
dalam contoh sebelumnya menekan mekanisme panggilan fungsi virtual.
Saran dan Komentar
https://aka.ms/ContentUserFeedback.
Segera hadir: Sepanjang tahun 2024 kami akan menghentikan penggunaan GitHub Issues sebagai mekanisme umpan balik untuk konten dan menggantinya dengan sistem umpan balik baru. Untuk mengetahui informasi selengkapnya, lihat:Kirim dan lihat umpan balik untuk