---
title: 'Sanal Fonksiyonlar ve Sanal Tablolar'
source: 'https://academia.sh/tr/kurslar/cpp-temelleri/sanal-fonksiyonlar-ve-sanal-tablolar'
course: 'C++ Temelleri ve Nesne Tasarımı'
language: tr
updated: '2026-09-26T03:02:46+00:00'
license: 'CC BY-SA 4.0'
objectives:
    - 'Sanal çağrının hangi işlevi çalıştıracağını nesnenin gerçek tipine göre seçtiğini gösterir'
    - 'Bir taban işaretçisi ya da referansı üzerinden yapılan çağrının hep aynı nesneyle çalıştığını ölçer'
    - 'Bir dizideki her taban işaretçisinin kendi gösterdiği nesneye ulaştığını, başka bir nesneye değil, doğrular'
---

# Sanal Fonksiyonlar ve Sanal Tablolar

Bir taban işaretçisi ya da referansı üzerinden yapılan sanal çağrının, ifadenin statik tipinden bağımsız olarak hep aynı nesneyle çalıştığının ölçümü.

Önceki ders, taban alt nesnenin türetilmiş nesnenin bir **parçası** olduğunu, adresinin
onunla çakıştığını ölçtü — ama hiçbir işlev `virtual` değildi, çağrılacak işlev
derleme zamanında ifadenin statik tipine bakılarak belirlendi. Bu ders `virtual`
anahtar sözcüğünü ekliyor: artık bir `Sekil*` ya da `Sekil&` üzerinden yapılan bir
çağrı, işaretçinin statik tipine değil, **gösterdiği nesnenin gerçek tipine** bakarak
hangi işlevi çalıştıracağına karar veriyor. Soru değişti: taban alt nesnenin adresi
değil, sanal bir çağrının gerçekte **hangi nesneyle** çalıştığı ölçülüyor.

## Sanal Çağrı Aynı Nesneye Ulaşıyor

`Dikdortgen`, `Sekil`'in `tanit` işlevini yeniden tanımlıyor. `d` nesnesine hem bir
`Sekil*` işaretçiyle hem bir `Sekil&` referansla erişilip `tanit` çağrıldığında, ikisi de
`d`'nin kendi işlevine mi ulaşıyor?

```cpp
// sanal_ayni_nesne.cpp — sanal cagri statik tipten bagimsiz olarak ayni nesneye ulasiyor
#include <iostream>

class Sekil {
public:
    virtual ~Sekil() = default;
    virtual void tanit(const void* beklenen) const {
        std::cout << "tanit(Sekil): calisan nesne beklenenle ayni mi "
                  << std::boolalpha << (static_cast<const void*>(this) == beklenen) << "\n";
    }
};

class Dikdortgen : public Sekil {
public:
    void tanit(const void* beklenen) const override {
        std::cout << "tanit(Dikdortgen): calisan nesne beklenenle ayni mi "
                  << std::boolalpha << (static_cast<const void*>(this) == beklenen) << "\n";
    }
};

int main() {
    Dikdortgen d;
    Sekil* taban_isaretci = &d;
    Sekil& taban_referans = d;

    taban_isaretci->tanit(&d);
    taban_referans.tanit(&d);

    return 0;
}
```

```
tanit(Dikdortgen): calisan nesne beklenenle ayni mi true
tanit(Dikdortgen): calisan nesne beklenenle ayni mi true
```

**CB4.** İki çağrı da statik tipi `Sekil` olan bir ifade üzerinden yapıldı
(`taban_isaretci`, `taban_referans`), ama ikisi de "tanit(Dikdortgen)" bastı — sanal
çağrı, işaretçinin/referansın statik tipine değil, gösterdiği nesnenin gerçek tipine
bakarak `Dikdortgen::tanit`'i seçti. İşlev içinde `this`, `d`'nin adresiyle
karşılaştırıldığında **true** dönüyor: çağrı yalnız doğru işlevi seçmekle kalmıyor,
seçtiği işlevi de tam olarak `d`'nin kendisi üzerinde çalıştırıyor, bir kopya ya da
başka bir nesne üzerinde değil. (M08/K02'de sorulan soru çağrıyı hangi tipin
çözdüğüydü; burada da benzer bir mekanizma var, ama ölçülen şey çağrının **hangi
nesneyle** çalıştığı — ve Java'da nesne dilimleme yokken C++'ta taban tipe değerle
atama yeni ve eksik bir nesne kurardı; burada yalnız işaretçi/referans erişimi var,
dilimleme devreye girmiyor.) M11/K03'ün Nesne Benzeri Tasarım dersinde elle kurulan
yöntem tablosu (işlev işaretçileri taşıyan bir struct) burada derleyicinin ürettiği
sanal işlev tablosuna karşılık geliyor; mekanizmanın ayrıntısı orada işlendi, burada yeniden
anlatılmıyor. Sınıf **kendisi**: `this`, çağrının yapıldığı ifadenin statik tipinden
bağımsız olarak hep `d`'nin adresini taşıyor.

## Taban İşaretçi Dizisi: Her Çağrı Kendi Nesnesine Ulaşıyor

Bir `Sekil*` dizisi farklı türetilmiş nesnelere işaret ettiğinde, her eleman kendi
gösterdiği nesneye mi ulaşıyor, yoksa aralarında bir karışma mı oluyor?

```cpp
// sanal_dizi.cpp — dizideki her taban isaretcisi kendi gosterdigi nesneye ulasiyor
#include <iostream>

class Sekil {
public:
    virtual ~Sekil() = default;
    virtual bool ayni_mi(const void* adres) const {
        return static_cast<const void*>(this) == adres;
    }
};

class Dikdortgen : public Sekil {};
class Ucgen : public Sekil {};

int main() {
    Dikdortgen d;
    Ucgen u;
    Sekil* sekiller[2] = { &d, &u };

    std::cout << std::boolalpha;
    std::cout << "sekiller[0] kendi nesnesi d ile ayni mi "
              << sekiller[0]->ayni_mi(&d) << "\n";
    std::cout << "sekiller[1] kendi nesnesi u ile ayni mi "
              << sekiller[1]->ayni_mi(&u) << "\n";
    std::cout << "sekiller[0] u ile ayni mi (capraz denetim) "
              << sekiller[0]->ayni_mi(&u) << "\n";

    return 0;
}
```

```
sekiller[0] kendi nesnesi d ile ayni mi true
sekiller[1] kendi nesnesi u ile ayni mi true
sekiller[0] u ile ayni mi (capraz denetim) false
```

**CB5.** `Dikdortgen` ve `Ucgen` `tanit`'i yeniden tanımlamıyor, `Sekil::ayni_mi`'yi
olduğu gibi devralıyor — ama işlev yine de her çağrıldığında `this`'i çağrıldığı
elemanın gösterdiği gerçek nesneye bağlıyor. `sekiller[0]->ayni_mi(&d)` **true**,
`sekiller[1]->ayni_mi(&u)` **true**: her eleman kendi nesnesine ulaşıyor. Çapraz
denetim bunu daha da netleştiriyor — `sekiller[0]` (`d`'yi gösteren eleman) `&u` ile
karşılaştırıldığında **false** dönüyor, çünkü `sekiller[0]`'ın çalıştığı nesne `d`,
`u` değil. Sınıf **kendisi**: dizideki her taban işaretçisi, aynı taban tipini taşısa
da, kendi gösterdiği tikel nesneden başka hiçbir nesneyle çalışmıyor.

## İşleve Referansla Geçirmek Nesneyi Değiştirmiyor

Bir işleve `const Sekil&` parametresiyle geçirilen bir nesne, işlev içinde hâlâ
dışarıdaki aynı nesne mi, yoksa işlevin kendi kopyası mı?

```cpp
// sanal_referans_parametre.cpp — isleve referansla gecirilen nesne disaridakiyle ayni
#include <iostream>

class Sekil {
public:
    virtual ~Sekil() = default;
    virtual bool ayni_mi(const void* adres) const {
        return static_cast<const void*>(this) == adres;
    }
};

class Dikdortgen : public Sekil {};

void dogrula(const Sekil& s, const void* beklenen) {
    std::cout << std::boolalpha
              << "islev icinde cagrilan nesne beklenenle ayni mi "
              << s.ayni_mi(beklenen) << "\n";
}

int main() {
    Dikdortgen d;
    dogrula(d, &d);
    return 0;
}
```

```
islev icinde cagrilan nesne beklenenle ayni mi true
```

**CB6.** `dogrula(d, &d)` çağrısında `s`, `d`'nin bir kopyası değil, `d`'nin kendisine
bağlanan bir referans — `const Sekil&` parametre türü bunu bir kopya kurmadan
sağlıyor. İşlev içinde `s.ayni_mi(&d)` çağrıldığında sanal çağrı yine `Sekil::ayni_mi`'yi
seçiyor (çünkü `Dikdortgen` onu yeniden tanımlamadı) ve `this`, dışarıdaki `d`'nin
adresiyle karşılaştırıldığında **true** dönüyor. İşlev sınırını geçmek — parametrenin
referans olması koşuluyla — nesnenin kimliğini değiştirmiyor: `dogrula` içindeki `s`,
`main` içindeki `d` ile aynı nesne. Sınıf **kendisi**: işlev çağrısı bir kopya
kurmadığı sürece, sanal çağrı hep çağrının başladığı yerdeki gerçek nesneyle çalışıyor.

## override ve final: Aynı Nesneye Yine de Gerçek Tipe Göre Ulaşmak

`KenarliUcgen`, `Ucgen`'den türeyen ve `ayni_mi`'yi hem `override` hem `final` olarak
işaretleyen, kendisi de `final` olan bir sınıf. Bu iki anahtar sözcük çalışma zamanı davranışını değil, derleme
zamanı denetimini etkiliyor — ama sonuçta çalışan sanal çağrı yine aynı nesneye mi
ulaşıyor?

```cpp
// sanal_override_final.cpp — override ve final ile isaretlenmis sanal cagri yine nesnenin gercek tipine gore calisiyor
#include <iostream>

class Sekil {
public:
    virtual ~Sekil() = default;
    virtual bool ayni_mi(const void* adres) const {
        return static_cast<const void*>(this) == adres;
    }
};

class Ucgen : public Sekil {
public:
    bool ayni_mi(const void* adres) const override {
        return static_cast<const void*>(this) == adres;
    }
};

class KenarliUcgen final : public Ucgen {
public:
    bool ayni_mi(const void* adres) const override final {
        return static_cast<const void*>(this) == adres;
    }
};

int main() {
    KenarliUcgen k;
    Sekil& taban_referans = k;

    std::cout << std::boolalpha
              << "taban referans uzerinden cagrilan ayni_mi beklenenle ayni mi "
              << taban_referans.ayni_mi(&k) << "\n";

    return 0;
}
```

```
taban referans uzerinden cagrilan ayni_mi beklenenle ayni mi true
```

**CB23.** `override`, derleyiciye "bu işlev bir taban sınıf işlevini yeniden
tanımlıyor" der ve imza eşleşmezse (örneğin `const` unutulursa, ya da parametre tipi
yanlış yazılırsa) derleme hatası çıkarır — imza kazara uyuşmayıp sessizce yeni, ayrı bir
işlev tanımlanmasını (ve taban işlevin hiç yeniden tanımlanmamasını) önler. Bu koruma
derleme zamanında işliyor; sandbox yalnız başarıyla derlenen kodu çalıştırdığından,
imza uyuşmazlığının nasıl bir hataya yol açtığı burada çalıştırılarak gösterilemiyor,
yalnız anlatılabiliyor. `final`, hem `KenarliUcgen` sınıfının hem `ayni_mi` işlevinin
daha fazla türetilmesini/yeniden tanımlanmasını derleme zamanında engelliyor — bu da
çalıştırılarak değil, yalnızca yasaklanan bir ihlalin derlenmemesiyle gözlenebilecek bir
şey. Çalışan kısım değişmedi: `taban_referans.ayni_mi(&k)` **true** basıyor, çünkü
`override`/`final` çalışma zamanı davranışını değiştirmiyor, yalnız hangi imzaların
geçerli sayılacağını daraltıyor. Sınıf **kendisi**: `final` bir sınıfın nesnesi de,
diğerleri gibi, sanal çağrının ulaştığı nesnenin ta kendisi.

## Sanal Yıkıcı: Taban İşaretçiyle Silme Doğru Zinciri Çalıştırıyor

`Sekil`'in yıkıcısı `virtual`. `new` ile kurulan bir `Dikdortgen` bir `Sekil*`
üzerinden `delete` edildiğinde, yıkım `Dikdortgen`'in kendi yıkıcısından mı başlıyor,
yoksa doğrudan `Sekil`'inkine mi atlıyor?

```cpp
// sanal_yikici_taban_isaretciyle_silme.cpp — sanal yikici taban isaretciyle silindiginde dogru yikim zincirini calistiriyor
#include <iostream>

class Sekil {
public:
    virtual ~Sekil() { std::cout << "Sekil yikici\n"; }
};

class Dikdortgen : public Sekil {
public:
    ~Dikdortgen() override { std::cout << "Dikdortgen yikici\n"; }
};

int main() {
    Sekil* taban_isaretci = new Dikdortgen();
    std::cout << "-- silme basliyor --\n";
    delete taban_isaretci;
    return 0;
}
```

```
-- silme basliyor --
Dikdortgen yikici
Sekil yikici
```

**CB24.** `taban_isaretci`'nin statik tipi `Sekil*`, ama `delete taban_isaretci`
çağrıldığında önce **Dikdortgen yikici** basılıyor, sonra **Sekil yikici** — yıkım da,
kurma gibi, en türemişten en tabana doğru işliyor, ve bunu doğru sırayla başlatabilen
şey `~Sekil()`'in `virtual` olması. Bu, standartın tanımladığı davranış: taban sınıfın
yıkıcısı sanal olduğunda, taban işaretçi üzerinden yapılan `delete` gerçek (dinamik)
tipin yıkıcısını çağırarak başlıyor. Karşılığının ise tanımlı bir sonucu yok: `~Sekil()`
`virtual` olmasaydı, statik ile dinamik tipin farklı olduğu bu `delete taban_isaretci`
standarda göre **tanımsız davranış** olurdu. Yaygın derleyicilerde bu çoğu zaman yalnız
`Sekil`'in yıkıcısının çalışması ve `Dikdortgen`'in eklediği kaynakların serbest
bırakılmaması biçiminde görülür, ama bu bir derleyici davranışıdır, dilin güvencesi
değildir. Bu dal burada çalıştırılmıyor: tanımsız davranış deterministik
bir çıktı vermeyeceğinden sandbox'ta doğrulanabilir bir sonucu yok, yalnız anlatılabilir.
Sınıf **kendisi**: `delete` çağrısı `taban_isaretci`'nin statik tipinden bağımsız olarak
hep `d`'nin (gerçek nesnenin) tam yıkım zincirini işletiyor.

## Elle Kurulan Yöntem Tablosu ile Derleyicinin Sanal İşlev Tablosu Aynı Sonucu Veriyor

M11/K03'ün Nesne Benzeri Tasarım dersi, işlev işaretçileri taşıyan bir `struct`
ile elle bir "yöntem tablosu" kurmuştu. Böyle elle kurulan bir tablo üzerinden yapılan
çağrı ile derleyicinin ürettiği sanal işlev tablosu üzerinden yapılan `virtual` çağrı, aynı
nesne için aynı sonucu mu veriyor?

```cpp
// sanal_el_ile_yontem_tablosu.cpp — elle kurulan yontem tablosu derleyicinin urettigi sanal islev tablosuyla ayni sonucu veriyor
#include <iostream>

struct Sekil {
    virtual ~Sekil() = default;
    virtual int alan() const { return 0; }
};

struct Kare : public Sekil {
    explicit Kare(int kenar) : kenar_(kenar) {}
    int alan() const override { return kenar_ * kenar_; }
    int kenar_;
};

struct ElleYontemTablosu {
    int (*alan)(const void*);
};

int kare_alan_el_ile(const void* nesne) {
    return static_cast<const Kare*>(nesne)->alan();
}

int main() {
    Kare kare(5);
    Sekil& sanal_erisim = kare;

    ElleYontemTablosu tablo{ kare_alan_el_ile };

    std::cout << "derleyicinin sanal cagrisi: " << sanal_erisim.alan() << "\n";
    std::cout << "elle kurulan tablo cagrisi: " << tablo.alan(&kare) << "\n";
    std::cout << std::boolalpha << "iki sonuc ayni mi "
              << (sanal_erisim.alan() == tablo.alan(&kare)) << "\n";

    return 0;
}
```

```
derleyicinin sanal cagrisi: 25
elle kurulan tablo cagrisi: 25
iki sonuc ayni mi true
```

**CB25.** `sanal_erisim.alan()` derleyicinin ürettiği sanal işlev tablosu üzerinden
`Kare::alan`'a ulaşıyor; `tablo.alan(&kare)` ise elle kurulan `ElleYontemTablosu`
üzerinden aynı işleve (bu kez doğrudan bir işlev işaretçisiyle) ulaşıyor. İkisi de
**25** basıyor ve karşılaştırma **true**: iki farklı mekanizma, aynı nesne için aynı
işlevi seçiyor. Fark, seçimin nasıl yapıldığında — sanal çağrıda derleyici her
nesneye gizli bir sanal işlev tablosu işaretçisi ekliyor ve `alan()` her çağrıldığında o
işaretçi üzerinden doğru girdiyi buluyor; elle kurulan tabloda bu adımı burada
`ElleYontemTablosu tablo{...}` satırı ve tabloyu doğru nesneyle eşleştirme
sorumluluğu programcıya ait. M11/K03'te bu mekanizma ayrıntılı işlendi; burada yalnız
iki yaklaşımın aynı sonuca vardığı doğrulanıyor. Sınıf **kendisi**: her iki çağrı da
`kare`'nin kendisi üzerinde çalışıyor.

## Sanal Dinamik Gönderimin Yapısal Maliyeti: Daha Büyük Nesne

`SanalNokta`, `SanalsizNokta` ile aynı iki `int` alanını taşıyor, tek farkla: bir sanal
yıkıcısı var. Aynı alanları taşıyan bu iki sınıf aynı boyutta mı, yoksa sanal işlev
taşımanın nesne başına bir yapısal bedeli mi var?

```cpp
// sanal_dinamik_gonderim_maliyeti.cpp — sanal islev tasiyan sinif ayni alanlari tasiyan sanal olmayan siniftan daha buyuk
#include <iostream>

class SanalsizNokta {
public:
    int x_ = 0;
    int y_ = 0;
};

class SanalNokta {
public:
    virtual ~SanalNokta() = default;
    int x_ = 0;
    int y_ = 0;
};

int main() {
    std::cout << std::boolalpha
              << "sanal islev tasiyan sinif, tasimayandan daha buyuk mu "
              << (sizeof(SanalNokta) > sizeof(SanalsizNokta)) << "\n";
    return 0;
}
```

```
sanal islev tasiyan sinif, tasimayandan daha buyuk mu true
```

**CB26.** İki sınıf birebir aynı iki `int` alanını taşıyor, ama karşılaştırma **true**:
`SanalNokta` daha büyük. Fark, `virtual` bir işlev tanımlanır tanımlanmaz derleyicinin
her nesneye eklediği gizli bir sanal işlev tablosu işaretçisinden geliyor — bu, dinamik
gönderimin **nesne başına, bir kerelik** yapısal bedeli. Bunun yanında bir de **çağrı
başına** bir bedel var: her sanal çağrı, doğrudan bir atlama yerine önce nesnenin sanal
işlev tablosu işaretçisi üzerinden doğru girdiyi bulan bir dolaylama yapıyor. Bu ikinci bedel
burada ölçülmüyor, çünkü süre ölçümü donanıma, derleyici optimizasyon düzeyine ve
sandbox'ın kendi yüküne bağlı olur — bu ders bu tür ortama bağlı verileri raporlamıyor.
Ölçülebilir ve deterministik olan yalnız boyut farkı. Sınıf **parça**: sanal işlev tablosu
işaretçisi nesnenin bir parçası, ayrı bir nesne değil.

## Yapıcı İçinde Sanal Çağrı: Türemişe Değil, Tabana Gidiyor

`Taban`'ın yapıcısı kendi gövdesi içinde `tanimla()`'yı çağırıyor; `Turemis` bu işlevi
yeniden tanımlıyor. Bir `Turemis` nesnesi kurulurken `Taban`'ın yapıcısı içindeki bu
çağrı `Turemis::tanimla`'ya mı ulaşıyor, yoksa `Taban::tanimla`'ya mı?

```cpp
// sanal_yapici_icinde_cagri.cpp — yapici icinde yapilan sanal cagri turemisin degil tabanin kendi islevine gidiyor
#include <iostream>

class Taban {
public:
    Taban() {
        std::cout << "Taban yapicisi icinde tanimla() cagriliyor\n";
        tanimla();
    }
    virtual void tanimla() const {
        std::cout << "Taban::tanimla calisti\n";
    }
};

class Turemis : public Taban {
public:
    Turemis() {
        std::cout << "Turemis yapicisi icinde tanimla() cagriliyor\n";
        tanimla();
    }
    void tanimla() const override {
        std::cout << "Turemis::tanimla calisti\n";
    }
};

int main() {
    Turemis t;
    return 0;
}
```

```
Taban yapicisi icinde tanimla() cagriliyor
Taban::tanimla calisti
Turemis yapicisi icinde tanimla() cagriliyor
Turemis::tanimla calisti
```

**CB27.** `t`'nin son hâli bir `Turemis`, ama `Taban`'ın yapıcısı çalışırken içindeki
`tanimla()` çağrısı **Taban::tanimla**'yı çalıştırıyor, `Turemis::tanimla`'yı değil.
Neden: `Taban`'ın yapıcısı çalıştığı sırada `Turemis`'in kendi parçası henüz
kurulmamış — nesnenin o andaki etkin tipi, sanal gönderim açısından, hâlâ `Taban`. Bu
zincir yukarı doğru ilerledikçe değişiyor: `Turemis`'in kendi yapıcısı çalışırken
yapılan `tanimla()` çağrısı artık **Turemis::tanimla**'yı çalıştırıyor, çünkü o noktada
nesnenin `Turemis` parçası da kurulmuş durumda. Sınıf **kendisi**: her iki çağrı da
`t`'nin ta kendisi üzerinde çalışıyor, ama hangi işlevin seçileceği, çağrının yapıldığı
anda inşa zincirinin nerede olduğuna bağlı.

## Sınırlayıcı Ölçüm

Bu derste ölçülen sanal çağrılar hep bir işaretçi ya da referans üzerinden yapıldı;
`Dikdortgen`'i **değerle** bir `Sekil` değişkenine atamak (`Sekil s = d;`) bu ölçümün
kapsamı dışında — böyle bir atama sanal çağrıyı değil, bir önceki dersin sonunda
değinilen dilimlemeyi devreye sokar ve sonuç yeni, eksik bir `Sekil` nesnesidir. Ölçüm
ayrıca `tanit`'in ve `ayni_mi`'nin kendi içinde başka bir sanal çağrı yapmadığı basit
durumları kapsıyor; bir taban yıkıcının sanal olmaması durumunda ortaya çıkabilecek
eksik yıkım bu derste hiç gözlenmedi, çünkü her iki sınıf da (`Sekil`, türetilenleri)
sanal bir yıkıcı taşıyor. Bir taban sınıfın hiç gövdesi olmayan, yalnız arayüz sunan
işlevlerle kurulması — soyut sınıflar — bu dersin konusu değil; bir sonraki ders bunu
ölçüyor.

## Özet

- Bir `Sekil*` ya da `Sekil&` üzerinden yapılan sanal çağrı, ifadenin statik tipine
  değil, gösterdiği nesnenin gerçek tipine bakarak hangi işlevi çalıştıracağına karar
  veriyor.
- Seçilen işlev içinde `this`, çağrının yapıldığı taban tipinden ifadeden bağımsız
  olarak hep aynı gerçek nesnenin adresini taşıyor — sınıf **kendisi**.
- Bir `Sekil*` dizisindeki her eleman kendi gösterdiği tikel nesneye ulaşıyor; çapraz
  denetim başka bir elemanın nesnesiyle eşleşmediğini doğruluyor.
- Bir işleve `const Sekil&` parametresiyle geçirilen nesne, işlev içinde de dışarıdaki
  aynı nesne — referans bağlama bir kopya kurmuyor.
- Taban tipe **değerle** atama (dilimleme) bu dersin kapsamı dışında; sanal çağrı yalnız
  işaretçi/referans erişiminde bu şekilde çalışıyor.

## Sonraki Adım

Bu derste `Sekil::tanit` ve `Sekil::ayni_mi`'nin bir gövdesi vardı — türetilmiş sınıflar
onu yeniden tanımlamasa da çağrılabiliyordu. Bir sonraki ders, Soyut Sınıflar ve
Arayüzler, bir taban sınıfın hiç gövdesi olmayan, yalnız bir sözleşme bildiren
işlevlerle kurulduğu durumu ölçüyor — orada taban sınıftan doğrudan bir nesne
kurulamıyor, yalnız türetilmiş sınıflardan; ölçülen yine bir sanal çağrının hangi
nesneyle çalıştığı, ama bu kez taban tipin kendi başına hiçbir örneği yok.
