Pokud ty (virtuální) metody budou různé, v objektovém jazyce stejně budete muse napsat každou zvlášť. A napsat si v C univerzální wrapper, který pro kteroukoli z těch struktur zavolá její vlastní close()
handler, je triviální.
Schválně se zkuste podívat na to, jak se v jádře pracuje třeba právě s těmi sockety ( struct sock
-- struct inet_sock
-- struct inet_connection_sock
-- struct tcp_sock
). Zjístíte, že dědičnost a polymorfismus nejsou zase až tak unikátním výdobytkem objektových jazyků, jak jste si možná myslel.
A ked pridam dalsi druh socketu cez nejaku kniznicu tak si musim napisat override na ten 'univerzalny' wrapper aby dokazal zavolat close() aj nad tou novou kniznicou namiesto toho aby proste kniznica zdedila zo socketu a implementovala svoj close() a ja nemusim nic pisat len stale zavolam xxx.close(). Netvrdim ze sa to neda len nevidim tu vyhodu pre ktoru by som to mal robit inac ako objektovo.
Ono je nakonec z praktického hlediska úplně jedno, jestli tomu říkáte virtuální metody nebo tabulka callbacků/handlerů. V praxi je to totéž a funguje to stejně, rozdíl je jen v té troše pohodlí. Samozřejmě i v tom, že objektový jazyk od vás odstíní, jak to ve skutečnosti funguje - ale tam už je diskutabilní, zda je to výhoda nebo nevýhodap; zajímalo by mne třeba, kolik programátorů v objektových jazycích si uvědomuje, jak moc jsou závislí na indirect callech a co pro ně prakticky znamená zavedení retpolines kvůli Spectre.
Netvrdil jsem, že je to výhodnější a když budu psát projekt v C++, tak samozřejmě použiju virtuální metody a ne strukturu s callbacky. Chtěl jsem jen upozornit, že objektový jazyk a jeho nástroje nejsou vůbec nutné pro techniky jako dědičnost a polymorfismus, protože to jde třeba i v C - a dokonce se to běžně dělá.