Bagikan melalui


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 Accountdasar .

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 DerivedNameOf 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.