Aracılığıyla paylaş


Sanal işlevler

Türetilmiş sınıfları yeniden tanımlanmasını beklediğiniz bir üye işlev bir sanal işlevdir.Bir işaretçi veya taban sınıfının bir başvurusunu kullanarak türetilmiş bir sınıf nesnesi için başvurduğunuzda, o nesne için sanal bir işlev çağrısı ve türetilmiş sınıfın işlev sürümünü çalıştırın.

Sanal işlevler işlev çağrısı yapmak için kullanılan deyim ne olursa olsun, bir nesne için doğru işlev denir emin olun.

Temel bir sınıf olarak bildirilen bir işlev içerdiğini varsayalım sanal ve türetilmiş bir sınıf aynı işlevi tanımlar.Bir işaretçi veya temel sınıf başvuru kullanılarak çağrılır bile işlevi türetilmiş sınıftan türetilmiş bir sınıf nesneleri için çağrılır.Aşağıdaki örnek uygulaması sağlayan bir temel sınıf gösterir PrintBalance işlevi ve iki türetilmiş sınıflar

// 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();   
}

Önceki kodda, çağrı PrintBalance nesne dışında birbirinin aynı olan pAccount işaret eder.Çünkü PrintBalance sanaldır, her nesne adı verilen için tanımlanan işlev sürümü.PrintBalance Türetilmiş sınıfları işlevinde CheckingAccount ve SavingsAccount "işlevi temel sınıfta geçersiz kıl" Account.

Bir sınıf, sağlamaz geçersiz kılma uygulaması bildirilmiş PrintBalance işlevi, varsayılan uygulama Temel sınıftan Account kullanılır.

Türetilmiş Sınıflar işlevlerinde türleri aynı ise, temel sınıflar sanal işlevleri geçersiz kılar.Türetilmiş bir sınıf içinde bir işlev dönüş türünün yalnızca bir taban sınıfta sanal bir işlevden farklı olamaz; bağımsız değişken listesi de farklı olması.

İşaretçileri veya başvuruları kullanarak bir işlevi çağırırken aşağıdaki kurallar uygulanır:

  • Sanal işlevine bir çağrı için adlandırılır nesne temel türüne göre çözümlenir.

  • Sanal olmayan bir işlev çağrısı, işaretçi veya başvuru türüne göre çözümlenir.

Aşağıdaki örnek, nasıl sanal ve sanal olmayan işlevler gösterir işaretçiler çağrıldığında davranır:

// 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.
}

0y01k918.collapse_all(tr-tr,VS.110).gifÇıktı

Derived::NameOf
Invoked by Base
Derived::NameOf
Invoked by Derived

Kullanılıp bakılmaksızın dikkat NameOf işlev işaretçi üzerinden çağrıldığında Base veya bir işaretçi Derived, işlevini çağırır Derived.İşlevini çağırır Derived çünkü NameOf sanal işlev ve her ikisi de pBase ve pDerived türünde bir nesneye işaret Derived.

Sanal işlevler yalnızca sınıf türü nesneler için denir çünkü genel veya statik işlev olarak bildiremezsiniz sanal.

Sanal türetilmiş bir sınıfta geçersiz kılma işlevleri bildirirken anahtar sözcük kullanılabilir, ancak gereksiz; geçersiz kılmaları sanal işlevlerin her zaman sanal.

Bir taban sınıftaki sanal işlevleri kullanılarak bildirilir sürece tanımlanmalı belirleyici saf.(Saf sanal işlevleri hakkında daha fazla bilgi için bkz: Soyut sınıflar.)

Sanal işlev çağrısı mekanizmasını açıkça kapsam çözünürlük operatörü kullanarak işlev adını nitelemek tarafından bastırılması (::).Önceki örnek maddelerle ilgili göz önünde Account sınıfı.Aranacak PrintBalance base sınıfında aşağıdaki gibi bir kod kullanın:

CheckingAccount *pChecking = new CheckingAccount( 100.00 );

pChecking->Account::PrintBalance();  //  Explicit qualification.

Account *pAccount = pChecking;  // Call Account::PrintBalance

pAccount->Account::PrintBalance();   //  Explicit qualification.

Yapılan her iki PrintBalance Yukarıdaki örnekte sanal işlev çağrısı mekanizması bastır.

Ayrıca bkz.

Başvuru

Sanal işlevlerine erişimi