Myöhäinen sidonta saadaan C++:ssa aikaan liittämällä virtual- avainsana metodien eteen. Kaikki ne metodit täytyy ilmoittaa myöhäiseen sidontaan, joita mahdolliset perilliset tulevat muuttamaan. Siis luokat vielä kerran remonttiin:
#include <iostream.h> #include <iomanip.h> class cAika { int h,m; public: virtual void aseta(int ih,int im=0) { // lisätty virtual h = ih; m = im; lisaa(0); } cAika(int ih=0, int im=0) { aseta(ih,im); } virtual void lisaa(int lisa_min) { // lisätty virtual int yht_min = h * 60 + m + lisa_min; h = yht_min / 60; m = yht_min % 60; } virtual void tulosta(int lf=1) const { // lisätty virtual cout << setfill('0') << setw(2) << h << ":" << setw(2) << m; if ( lf ) cout << endl; } }; class cAikaSek : public cAika { int s; public: virtual void aseta(int ih=0, int im=0) { cAika::aseta(ih,im); } // lisätty virtual void aseta(int ih, int im, int is) { // lisätty virtual s = is; aseta(ih,im); lisaa(0,0); // pois cAika:: } cAikaSek(int ih=0, int im=0, int is=0) { aseta(ih,im,is); } virtual void lisaa(int lisa_min) { cAika::lisaa(lisa_min); } // lisätty virtual void lisaa(int lisa_min, int lisa_sek) { // lisätty virtual s += lisa_sek; lisaa(lisa_min+s/60); s %= 60; // pois cAika:: } virtual void tulosta(int lf=1) const { // lisätty virtual cAika::tulosta(0); cout << ":" << setw(2) << s; if ( lf ) cout << endl; } }; int main(void) .. kuten aikacla8.cpp + cAika *pAika; ...Virtual sanat on lisätty kaikkien metodien eteen. Aliluokassa virtual on tarpeeton uudelleenmääriteltävien (korvaaminen, syrjäyttäminen, overriding) metodien kohdalle, mutta se on hyvä pitää siellä kommenttimielessä.
Sitten tuleekin hankalammin selitettävä asia. Miksi yksi- parametrinen lisaa ja kaksi- parametrinen aseta on täytynyt kirjoittaa uudelleen? Tämä johtuu kielen ominaisuuksista, sillä muuten vastaavat useampi- parametriset metodit syrjäyttäisivät alkuperäiset metodit ja alkuperäisiä ei olisi lainkaan käytössä. Tässä tapauksessa olisimmekin voineet antaa niiden syrjäytyä, mutta koska tulevaisuudesta ei koskaan tiedä, on alkuperäiselläkin parametrimäärällä olevien metodien ehkä hyvä säilyä.
Parempi ratkaisu olisi ehkä kuitenkin ollut, jos jo alkuperäisessä luokassa olisi varauduttu sekuntien tuloon, vaikka niitä ei olisi mitenkään otettukaan huomioon:
... class cAika { // Muutokset aikacla8.cpp:hen verrattuna int h,m; public: virtual void aseta(int ih=0,int im=0, int lisa_sek=0) { // virtual, lisa_sek h = ih; m = im; lisaa(0); } cAika(int ih=0, int im=0) { aseta(ih,im); } virtual void lisaa(int lisa_min, int lisa_sek=0) { // virtual, lisa_sek int yht_min = h * 60 + m + lisa_min; h = yht_min / 60; m = yht_min % 60; } virtual void tulosta(int lf=1) const { ... } // virtual }; class cAikaSek : public cAika { int s; public: virtual void aseta(int ih=0, int im=0, int is=0) { // virtual s = is; cAika::aseta(ih,im); lisaa(0); // järj. vaihd. } cAikaSek(int ih=0, int im=0, int is=0) { aseta(ih,im,is); } virtual void lisaa(int lisa_min, int lisa_sek=0) { // virtual s += lisa_sek; cAika::lisaa(lisa_min+s/60); s %= 60; } virtual void tulosta(int lf=1) const { // virtual }; ... int main(void) { ... cAika *pAika; pAika = &a1; pAika->tulosta(); pAika = &a4; pAika->tulosta(); return 0; }
Varoitus: Borlandin C++5.1:en optimoivalla kääntäjällä käännettynä em. koodi kaatoi kääntäjän ympäristöineen jos cAikaSek::aseta oli muodossa:
cAika::aseta(ih,im); s = is; lisaa(0);