Az elõzõ részekben egy összetett grafikus programrendszer lehetséges alaptípusainak példáján mutattuk be az OOP egyes jellemzõit. A point típus a location-ból lett származtatva, ugyanígy point-ból létrehozhatunk egy vonalakat leíró osztályt, amelyet például line-nak nevezhetünk, és mondjuk line-ból származtathatunk mindenféle poligont. A poligonokra két vázlatos példát mutattunk (triangle, rectangle), ezekbõl felépítve pedig már egy "valóságos" objektumok leírására való típus, a house vázlatos leírását adtuk. (Ezek a példák természetesen nem egy mûködõ program létrehozására, hanem sokkal inkább egy-egy OOP fogalom megvilágítására voltak kihegyezve.) Az eddigi példák többségének ugyanakkor volt egy közös vonása, nevezetesen az, hogy deklaráltunk bennük egy-egy show azonosítójú függvénymezõt azzal a céllal, hogy az az adott típusú objektumot a képernyõn megjelenítse. Az alapvetõ különbség az általunk elképzelt objektumtípusok között az, hogy milyen módon kell õket a képernyõre kirajzolni. Az egésznek van egy nagy hátránya: akárhányszor egy újabb alakzatot leíró osztályt definiálunk, a hozzátartozó show függvényt mindannyiszor újra kell írnunk. Ennek az az oka, hogy a C++ alapvetõen háromféleképpen tudja az azonos névvel ellátott függvényeket egymástól megkülönböztetni:
Egy komolyabb grafikus rendszer esetében azonban igen gyakran elõfordul az a helyzet, hogy csak az osztálydeklarációk állnak rendelkezésre forrásállományban (.h kiterjesztésû include file-okban), maguk a függvénymezõ definíciók pedig csak tárgykód formájában vannak meg (.obj file-okban). Ebben az esetben, ha a felhasználó a meglévõ osztályokból akar újabbakat származtatni, akkor a korai kötés korlátai miatt nem lesz könnyû dolga az alakzatmegjelenítõ rutinok megírásánál. A C++ ezt a problémát az ún. késõi kötés (late binding) lehetõségével hidalja át. Ezt a késõi kötést speciális függvénymezõk, a virtuális függvények (virtual functions) teszik lehetõvé.
Az alapkoncepció az, hogy a virtuális függvényhívásokat csak futási idõben oldja fel a C++ rendszer - innen származik a késõi kötés elnevezés. Tehát azt a döntést, hogy például melyik show függvényt is kell aktivizálni, el lehet halasztani egészen addig a pillanatig, amikor a ténylegesen megjelenítendõ objektum pontos típusa ismertté nem válik a program futása során. Egy virtuális show függvény, amely el van "rejtve" egy elõzetesen lefordított modulkönyvtár egy B alaposztályában, nem lesz véglegesen hozzárendelve a B típusú objektumokhoz olyan módon, ahogy azt normál függvénymezõk esetében láttuk. Nyugodtan származtathatunk egy D osztályt a B-bõl, definiálhatjuk a D típusú objektumok megjelenítésére szolgáló show függvényt. Az új forrásprogramot (amelyik az új D osztály definícióját is tartalmazza) lefordítva kapunk egy .obj file-t, amelyet hozzászerkeszthetünk a grafikus könyvtárhoz (a .lib file-hoz). Ezután a show függvényhívások, függetlenül attól, hogy a B alaposztálybeli függvénymezõre, vagy az új, D osztálybeli függvénymezõre vonatkoznak, helyesen lesznek végrehajtva. Lássuk ezt az egész fogalomkört egy kevésbé absztrakt példán.
Tekintsük a jól bevált point típust, és egészítsük ki azt egy olyan függvénnyel, amelyik egy ilyen típusú objektum által reprezentált pontot a képernyõ egyik helyérõl áthelyezi egy másikra helyre. A point-ból azután származtassunk egy körök leírására alkalmas circle típust (olyan meggondolás alapján, hogy egy pont egy olyan kör, amelynek sugara 0, tehát a point típust egyetlen adatmezõvel, a sugárral kell kiegészíteni).
enum colortype { black, red, blue, green, yellow, white }; class location { protected: int x; int y; public: location(int ix, int iy); ~location(void); int get_x(void); int get_y(void); }; class point : public location { protected: colortype color; public: colortype get_color(void); void show(void); void hide(void); void move(int dx, int dy); point(int ix,int iy); ~point(void); }; // A point:: fuggvenyek definicioja: ... void point::move(int dx, int dy) { // dx, dy offsetekkel athelyezi if (color) hide( ); // Ez itt a point::hide x += dx; y += dy; if (color) show( ); // Ez itt a point::show } class circle : public point { protected: int radius; // A sugara public: // Konstruktorhoz kezdeti x,y,r circle(int ix,int iy,int ir); colortype get_color(void); void show(void); void hide(void); void move(int dx, int dy); void zoom(int factor); }; // A circle:: fuggvenyek definicioja: ... void circle::move(int dx, int dy) { // dx, dy offsetekkel athelyezi if (color) hide( ); // Ez itt a circle::hide x += dx; y += dy; if (color) show( ); // Ez itt a circle::show } ...Figyeljük meg, hogy a két move függvény mennyire egyforma! A visszatérési típusuk void és a paraméter-szignatúrájuk is azonos, sõt, még a függvénytörzsek is azonosnak tûnnek. Hát akkor mi alapján tudja a fordító, hogy mikor melyik függvényrõl van szó? Ez esetben - ahogy azt a normál függvénymezõk esetében láttuk - a move függvényeink abban különböznek, hogy más-más osztályhoz tartoznak ( point::move, illetve circle::move). Fölvetõdik a kérdés: Ha a két move függvény törzse is egyforma, akkor miért kell belõlük 2 példány, miért ne örökölhetné circle ezt a függvényt point-tól? Nos azért, mert csak felületes ránézésre egyforma a két függvénytörzs, ugyanis más-más hide, illetve show függvényeket hívnak - ezeknek csak a neve és a szignatúrája azonos. Ha circle a point-tól örökölné a move függvényt, akkor az nem a megfelelõ hide, illetve show függvényeket hívná: nevezetesen a körre vonatkozó függvények helyett a pontra vonatkozókat aktivizálná. Ez azért van így, mert a korai kötés következtében a point::hide, illetve a point::show lenne a point típus move függvényéhez hozzárendelve, és az öröklés által a circle típus move függvénye is ezeket függvényeket hívná. Ezt a problémát úgy oldhatjuk meg, ha a show, illetve a hide függvényeket virtuális fügvényekként deklaráljuk. Ekkor nyugodtan írhatunk egy közös move függvényt a point és a circle számára (pontosabban fogalmazva a circle típus örökölhetné a point típus move függvényét), és majd futási idõben fog kiderülni, hogy melyik show, illetve hide függvényt kell meghívni.