Source

PensarEnC++ / V1-C15.xml

The branch 'PensarEnC++' does not exist.
Full commit
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
<?xml  version="1.0" encoding="utf-8"?>
<!-- -*- sgml -*- -->
<!--
  Editor:              Emacs 21/PSGML
  Traducción original: Jesús López Mollo <i302154@correo.unnet.es>
                       (anterior a LuCaS)

  Formateado DocBook:  David Villa <dvilla@gmx.net>
  1ª Revisión:
  2ª Revisión
-->

<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
                 "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">

<chapter
  xmlns:xi="http://www.w3.org/2001/XInclude"
  id="C15">

  <title>Polimorfismo y Funciones virtuales</title>

  <highlights>
    <para>
      El Polimorfismo (implementado en C++ con funciones
      <kw>virtual</kw>es) es la tercera característica esencial de un
      lenguaje orientado a objetos, después de la abstracción de datos y
      la herencia.
    </para>
  </highlights>

  <para>
    De hecho, nos provee de otra dimensión para la separación entre
    interfaz y la implementación, desacoplando el <emphasis>qué</emphasis>
    del <emphasis>cómo</emphasis>. El Polimorfismo permite mejorar la
    organización del código y su legibilidad así como la creación de
    programas <emphasis>extensibles</emphasis> que pueden "crecer" no sólo
    durante el desarrollo del proyecto, si no también cuando se deseen
    nuevas características.
  </para>

  <para>
    La encapsulación crea nuevos tipos de datos combinando
    características y comportamientos. El control de acceso separa la
    interfaz de la implementación haciendo privados
    (<kw>private</kw>) los detalles. Estos tipos de
    organización son fácilmente entendibles por cualquiera que venga de
    la programación procedimental. Pero las funciones virtuales tratan
    de desunir en términos de <emphasis>tipos</emphasis>. En el Capítulo
    14, usted vió como la herencia permitía tratar a un objeto como su
    propio tipo <emphasis>o</emphasis> como a su tipo base. Esta habilidad
    es básica debido a que permite a diferentes tipos (derivados del
    mismo tipo base) ser tratados como si fueran un único tipo, y un
    único trozo de código es capaz de trabajar indistintamente con
    todos. Las funciones virtuales permiten a un tipo expresar sus
    diferencias con respecto a otro similar si ambos han sido derivados
    del mismo tipo base. Esta distinción se consigue modificando las
    conductas de las funciones a las que se puede llamar a través de la
    clase base.
  </para>

  <para>
    En este capítulo aprenderá sobre las funciones virtuales, empezando
    con ejemplos simples que le mostrará lo "desvirtual" del programa.
  </para>

  <sect1>
    <title>Evolución de los programadores de C++</title>

    <para>
      Los programadores de C parecen conseguir pasarse a C++ en tres
      pasos. Al principio, como un "C mejorado", debido a que C++ le
      fuerza a declarar todas las funciones antes de usarlas y a que es
      mucho más sensible a la forma de usar las variables. A menudo se
      pueden encontrar errores en un programa C simplemente
      recompilándolo con un compilador de C++.
    </para>

    <para>
      El segundo paso es la "programación basada en objetos", que
      significa que se pueden ver fácilmente los beneficios de la
      organización del código al agrupar estructuras de datos junto con
      las funciones que las manejan, la potencia de los constructores y
      los destructores, y quizás algo de herencia simple. La mayoría de
      los programadores que han trabajado durante un tiempo con C ven la
      utilidad de esto porque es lo que intentan hacer cuando crean una
      librería. Con C++ usted recibe la ayuda del compilador.
    </para>

    <para>
      Usted se puede encontrar atascado en el nivel de "programación
      basada en objetos" debido a que es de fácil acceso y no requiere
      mucho esfuerzo mental. Es también sencillo sentir cómo está
      creando tipos de datos - usted hace clases y objetos, envía
      mensajes a esos objetos, y todo es bonito y pulcro.
    </para>

    <para>
      Pero no sea tonto. Si se para aquí, se está perdiendo una de las más
      importantes partes del lenguaje, que significa el salto a la
      verdadera programación orientada a objetos. Y esto se consigue
      únicamente con las funciones virtuales.
    </para>

    <para>
      Las funciones virtuales realzan el concepto de tipo en lugar de
      simplemente encapsular código dentro de estructuras y dejarlo
      detrás de un muro, por lo que son, sin lugar a dudas, el concepto
      más difícil a desentrañar por los nuevos programadores en
      C++. Sin embargo, son también el punto decisivo para comprender la
      programación orientada a objetos. Si no usa funciones virtuales,
      todavía no entiende la POO.
    </para>

    <para>
      Debido a que las funciones virtuales están intimamente unidas al
      concepto de tipo, y los tipos son el núcleo de la programación
      orientada a objetos, no existe analogía a las funciones virtuales
      dentro de los lenguajes procedurales. Como programador procedural,
      usted no tiene referente con el que comparar las funciones
      virtuales, al contrario de las otras características del
      lenguaje. Las características de un lenguaje procedural pueden ser
      entendidas en un nivel algorítmico, pero las funciones virtuales
      deben ser entendidas desde el punto de vista del diseño.
    </para>
  </sect1>

  <sect1>
    <title>Upcasting</title>

    <para>
      En el Capítulo 14 se vió como un objeto puede ser usado como un
      objeto de su propio tipo o como un objeto de su tipo base. Además
      el objeto puede ser manejado a través de su tipo base. Tomar la
      dirección de un objeto (o un puntero o una referencia) y tratarlo
      como la dirección de su tipo base se conoce como
      <foreignphrase>upcasting</foreignphrase>
	<footnote>
	  <para>
	    N del T: Por desgracia <literal>upcasting</literal> es otro
	    de los términos a los que no he encontrado una traducción
	    convincente (¿¿amoldar hacia arriba??) y tiene el agravante
	    que deriva de una expresión ampliamente usada por los
	    programadores de C (¿Quién no ha hecho nunca un
	    <literal>cast a void*</literal> ;-) ?. Se aceptan
	    sugerencias.
	  </para>
	</footnote>
	debido al camino que se genera en los árboles de herencia que
	se suelen pintar con la clase base en la cima.
    </para>

    <para>
      También se vió surgir un problema el cuál está encarnado en el
      siguiente código:
    </para>


//: V1C15:Instrument2.cpp


    <para>
      La función <function>tune()</function> acepta (por referencia) un
      <classname>Instrument</classname>, pero también acepta cualquier
      cosa que derive de <classname>Instrument</classname>. En el
      <function>main()</function>, se puede ver este comportamiento
      cuando se pasa un objeto <classname>Wind</classname> a
	<function>afinar() </function> sin que se necesite ningún molde. La
      interfaz de <classname>Instrument</classname> tiene que existir en
      <classname>Wind</classname>, porque <classname>Wind</classname>
      hereda sus propiedades de <classname>Instrument</classname>. Moldear
      en sentido ascendente (<foreignphrase>Upcasting</foreignphrase>) de
      <classname>Wind</classname> a <classname>Instrument</classname> puede
      "reducir" la interfaz, pero nunca puede ser menor que la interfaz
      de <classname>Instrument</classname>.
    </para>

    <para>
      Los mismos argumentos son ciertos cuando trabajamos con punteros;
      la única diferencia es que el usuario debe indicar la dirección de
      los objtos de forma explícita cuando se pasen a una
      función.
    </para>
  </sect1>


  <sect1>
    <title>El problema</title>

    <para>
      El problema con <filename>Instrument2.cpp</filename> puede verse
      al ejecutar el programa. La salida es
      <computeroutput>Instrument::play</computeroutput>. Claramente,
      esta no es la salida deseada, porque el objeto es actualmente un
      <classname>Wind</classname> y no solo un
      <classname>Instrument</classname>. La llamada debería producir un
      <computeroutput>Wind::play</computeroutput>. Por este motivo,
      cualquier objeto de una clase que derive de la clase
      <classname>Instrument </classname> debería usar su propia versión
      de <function>play()</function>, de acuerdo a la situación.
    </para>

    <para>
      El comportamiento de <filename>Instrument2.cpp</filename> no es
      sorprendente dada la aproximación de C a las funciones. Para
      entender el resultado es necesario comprender el concepto de
      <foreignphrase>binding</foreignphrase> (ligadura).
    </para>

    <sect2>
      <title>Ligadura de las llamadas a funciones</title>

      <para>
	Conectar una llamada a una función al cuerpo de la función se
	conoce como <foreignphrase>binding</foreignphrase>
	(vincular). Cuando la vinculación se realiza antes de ejecutar
	el programa (por el compilador y el linker), se la conoce como
	<foreignphrase>early binding</foreignphrase> (ligadura
	temprana). Puede no haber escuchado anteriormente este término
	debido a que no es posible con los lenguajes procedurales: los
	compiladores de C sólo admiten un tipo de vinculación que es la
	vinculación anticipada.
      </para>

      <para>
	El problema en el programa anterior es causado por la
	vinculación anticipada porque el compilador no conoce la
	correcta función a la que debería llamar cuando sólo es una
	dirección de <classname>Instrument</classname>.
      </para>

      <para>
	La solución se conoce como ligadura tardía (<foreignphrase>late
	binding</foreignphrase>), que significa que la ligadura se
	produce en tiempo de ejecución basándose en el tipo de
	objeto. También es conocida como <emphasis>ligadura
	dinámica</emphasis> o <emphasis>ligadura en tiempo de
	ejecución</emphasis>. Cuando un lenguaje implementa la ligadura
	dinámica debe existir algún tipo de mecanismo para determinar el
	tipo del objeto en tiempo de ejecución y llamar a la función
	miembro apropiada. En el caso de un lenguaje compilado, el
	compilador todavía no conoce el tipo actual del objeto, pero
	inserta código que lo averigua y llama al cuerpo correcto de la
	función. El mecanismo de la ligadura dinámica varía de un
	lenguaje a otro, pero se puede imaginar que algún tipo de
	información debe ser introducida en los objetos. Se verá como
	trabaja posteriormente.
      </para>
    </sect2>
  </sect1>

  <sect1>
    <title>Funciones virtuales</title>
    <para>
      Para que la ligadura dinámica tenga efecto en una función
      particular, C++ necesita que se use la palabra reservada
      <kw>virtual</kw> cuando se declara la función en la
      clase base. La ligadura en tiempo de ejecución funciona
      unícamente con las funciones <kw>virtual</kw> es, y sólo
      cuando se está usando una dirección de la clase base donde exista
      la función <kw>virtual</kw>, aunque puede ser definida
      también en una clase base anterior.
    </para>

    <para>
      Para crear una función miembro como <kw>virtual</kw>,
      simplemente hay que preceder a la declaración de la función con la
      palabra reservada <kw>virtual</kw>. Sólo la declaración
      necesita la palabra reservada <kw>virtual</kw>, y no la
      definición. Si una función es declarada como
      <kw>virtual</kw>, en la clase base, será entonces
      <kw>virtual</kw> en todas las clases derivadas. La
      redefinición de una función <kw>virtual</kw> en una
      clase derivada se conoce como <foreignphrase>overriding</foreignphrase>.
    </para>

    <para>
      Hay que hacer notar que sólo es necesario declarar la función como
      <kw>virtual</kw> en la clase base. Todas las funciones
      de las clases derivadas que encajen con la declaración que esté en
      la clase base serán llamadas usando el mecanismo virtual. Se
      <emphasis>puede</emphasis> usar la palabra reservada
      <kw>virtual</kw> en las declaraciones de las clases
      derivadas (no hace ningún mal), pero es redundante y puede causar
      confusión.
    </para>

    <para>
      Para conseguir el comportamiento deseado de
      <filename>Instrument2.cpp</filename>, simplemente hay que añadir la
      palabra reservada <kw>virtual</kw> en la clase base
      antes de <function>play()</function>.
    </para>


//: V1C15:Instrument3.cpp


    <para>
      Este archivo es idéntico a <filename>Instrument2.cpp</filename>
      excepto por la adición de la palabra reservada
      <kw>virtual</kw> y, sin embargo, el comportamiento es
      significativamente diferente: Ahora la salida es
      <computeroutput>Wind::play</computeroutput>.
    </para>

    <sect2>
      <title>Extensibilidad</title>

      <para>
	Con <function>play()</function> definido como
	<kw>virtual</kw> en la clase base, se pueden añadir
	tantos nuevos tipos como se quiera sin cambiar la función
	<function>play()</function>. En un programa orientado a objetos
	bien diseñado, la mayoría de las funciones seguirán el modelo de
	<function>play()</function> y se comunicarán únicamente a través
	de la interfaz de la clase base. Las funciones que usen la
	interfaz de la clase base no necesitarán ser cambiadas para
	soportar a las nuevas clases.
      </para>

      <para>
	Aquí está el ejemplo de los instrumentos con más funciones
	virtuales y un mayor número de nuevas clases, las cuales
	trabajan de manera correcta con la antigua (sin modificaciones)
	función <function>play()</function>:
      </para>


//: V1C15:Instrument4.cpp



      <para>
	Se puede ver que se ha añadido otro nivel de herencia debajo de
	<classname>Wind</classname>, pero el mecanismo
	<kw>virtual</kw> funciona correctamente sin importar
	cuantos niveles haya. La función <function>adjust()</function>
	<emphasis>no</emphasis> está redefinida
	(<foreignphrase>override</foreignphrase>) por
	<classname>Brass</classname> y
	<classname>Woodwind</classname>. Cuando esto ocurre, se usa la
	definición más "cercana" en la jerarquía de herencia - el
	compilador garantiza que exista <emphasis>alguna</emphasis>
	definición para una función virtual, por lo que nunca acabará en
	una llamada que no esté enlazada con el cuerpo de una función
	(lo cual sería desatroso).
      </para>

      <para>
	El array <literal>A[]</literal> contiene punteros a la clase
	base <classname>Instrument</classname>, lo que implica que
	durante el proceso de inicialización del array habrá
	<foreignphrase>upcasting</foreignphrase>. Este array y la
	función <function>f()</function> serán usados en posteriores
	discusiones.
      </para>

      <para>
	En la llamada a <function>tune()</function>, el
	<foreignphrase>upcasting</foreignphrase> se realiza en cada tipo
	de objeto, haciendo que se obtenga siempre el comportamiento
	deseado. Se puede describir como "enviar un mensaje a un objeto
	y dejar al objeto que se preocupe sobre qué hacer con él". La
	función <kw>virtual</kw> es la lente a usar cuando
	se está analizando un proyecto: ¿Dónde deben estar las clases
	base y cómo se desea <emphasis>extender</emphasis> el programa?
	Sin embargo, incluso si no se descubre la interfaz apropiada
	para la clase base y las funciones virtuales durante la creación
	del programa, a menudo se descubrirán más tarde, incluso mucho
	más tarde cuando se desee ampliar o se vaya a hacer funciones de
	mantenimiento en el programa. Esto no implica un error de
	análisis o de diseño; simplemente significa que no se conocía o
	no se podía conocer toda la información al principio. Debido a
	la fuerte modularización de C++, no es mucho problema que esto
	suceda porque los cambios que se hagan en una parte del sistema
	no tienden a propagarse a otras partes como sucede en C.
      </para>
    </sect2>
  </sect1>

  <sect1>
    <title>Cómo implementa C++ la ligadura dinámica</title>

    <para>
      ¿Cómo funciona la ligadura dinámica? Todo el trabajo se realiza
      detrás del telón gracias al compilador, que instala los mecanismos
      necesarios de la ligadura dinámica cuando se crean funciones
      virtuales. Debido a que los programadores se suelen beneficiar de
      la comprensión del mecanismo de las funciones virtuales en C++,
      esta sección mostrará la forma en que el compilador implementa
      este mecanismo.
    </para>

    <para>
      La palabra reservada <kw>virtual</kw> le dice al
      compilador que no debe realizar ligadura estática. Al
      contrario, debe instalar automáticamente todos los mecanismos
      necesarios para realizar la ligadura dinámica. Esto significa
      que si se llama a <function>play()</function> para un objeto
      <classname>Brass</classname> a <emphasis>través una dirección a la
      clase base</emphasis> <classname>Instrument</classname>, se usará la
      función apropiada.
    </para>

    <para>
	Para que funcione, el compilador típico
	<footnote>
	  <para>
	    Los compiladores pueden implementar el comportamiento
	    virtual como quieran, pero el modo aquí descrito es una
	    aproximación casi universal.
	  </para>
	</footnote>
	crea una única tabla (llamada VTABLE) por cada clase que
      contenga funciones <literal>virtuales</literal>. El compilador
      coloca las direcciones de las funciones virtuales de esa clase en
      concreto en la VTABLE. En cada clase con funciones virtuales el
      compilador coloca de forma secreta un puntero llamado
      <literal>vpointer</literal> (de forma abreviada VPTR), que apunta
      a la VTABLE de ese objeto. Cuando se hace una llamada a una
      función virtual a través de un puntero a la clase base (es decir,
      cuando se hace una llamada usando el polimorfismo), el compilador
      silenciosamente añade código para buscar el VPTR y así conseguir
      la dirección de la función en la VTABLE, con lo que se llama a la
      función correcta y tiene lugar la ligadura dinámica.
    </para>

    <para>
      Todo esto - establecer la VTABLE para cada clase, inicializar el
      VPTR, insertar código para la llamada a la función virtual -
      sucede automáticamente sin que haya que preocuparse por ello. Con
      las funciones virtuales, se llama a la función apropiada de un
      objeto, incluso aunque el compilador no sepa el tipo exacto del
      objeto.
    </para>

<!--
<notapie>
<negrita>3: </negrita>
</notapie>
-->

    <sect2>
      <title>Almacenando información de tipo</title>

      <para>
	Se puede ver que no hay almacenada información de tipo de forma
	explícita en ninguna de las clases. Pero los ejemplos
	anteriores, y la simple lógica, dicen que debe existir algún
	tipo de información almacenada en los objetos; de otra forma el
	tipo no podría ser establecido en tiempo de ejecución. Es
	verdad, pero la información de tipo está oculta. Para verlo,
	aquí está un ejemplo que muestra el tamaño de las clases que
	usan funciones virtuales comparadas con aquellas que no las
	usan:
      </para>


//: V1C15:Sizes.cpp


      <para>
	Sin funciones virtuales el tamaño del objeto es exactamente el
	que se espera: el tamaño de un único
	<footnote>
	  <para>
	    Algunos compiladores pueden aumentar el tamaño pero sería
	    raro.
	  </para>
	</footnote> <type>int</type>.  Con una única función
	virtual en <classname>OneVirtual</classname>, el tamaño del
	objeto es el tamaño de <classname>NoVirtual</classname> más el
	tamaño de un puntero a <type>void</type>. Lo que implica
	que el compilador añade un único puntero (el VPTR) en la
	estructura si se tienen una <emphasis>o más</emphasis> funciones
	virtuales. No hay diferencia de tamaño entre
	<classname>OneVirtual</classname> y
	<classname>TwoVirtuals</classname>. Esto es porque el VPTR
	apunta a una tabla con direcciones de funciones. Se necesita
	sólo una tabla porque todas las direcciones de las funciones
	virtuales están contenidas en esta tabla.
      </para>

      <para>
	Este ejemplo requiere como mínimo un miembro de datos. Si no
	hubiera miembros de datos, el compilador de C++ hubiera forzado
	a los objetos a ser de tamaño no nulo porque cada objeto debe
	tener direcciones distintas (¿se imagina cómo indexar un array
	de objetos de tamaño nulo?). Por esto se inserta en el objeto un
	miembro "falso" ya que de otra forma tendríá un tamaño
	nulo. Cuando se inserta la información de tipo gracias a la
	palabra reservada <kw>virtual</kw>, ésta ocupa el
	lugar del miembro "falso". Intente comentar el <literal>int
	a</literal> en todas las clases del ejemplo anterior para
	comprobarlo.
      </para>
    </sect2>


    <sect2>
      <title>Pintar funciones virtuales</title>

      <para>
	Para entender exactamente qué está pasando cuando se usan
	funciones virtuales, es útil ver la actividad que hay detrás del
	telón. Aquí se muestra el array de punteros
	<literal>A[]</literal> in <filename>Instrument4.cpp</filename>:
      </para>

      <figure>
	<title>Funciones virtuales</title>
	<mediaobject>
	  <imageobject role="latex">
	    <imagedata fileref="./images/V1_16.pdf" align="center" format="PDF"/>
	  </imageobject>
	  <imageobject role="html">
	    <imagedata fileref="./images/V1_16.png" align="center" format="PNG"/>
	  </imageobject>
	</mediaobject>
      </figure>

      <para>
	El array de punteros a <classname>Instrument</classname>s no
	tiene información específica de tipo; cada uno de ellos apunta a
	un objeto de tipo
	<classname>Instrument</classname>. <classname>Wind</classname>,
	<classname>Percussion</classname>,
	<classname>Stringed</classname>, y <classname>Brass</classname>
	encajan en esta categoría porque derivan de
	<classname>Instrument</classname> (esto hace que tengan la misma
	interfaz de <classname>Instrument</classname>, y puedan
	responder a los mismos mensajes), lo que implica que sus
	direcciones pueden ser metidas en el array. Sin embargo, el
	compilador no sabe que sean otra cosa que objetos de tipo
	<classname>Instrument</classname>, por lo que normalmente
	llamará a las versiones de las funciones que estén en la clase
	base. Pero en este caso, todas las funciones han sido declaradas
	con la palabra reservada <kw>virtual</kw>, por lo que
	ocurre algo diferente. Cada vez que se crea una clase que
	contiene funciones virtuales, o se deriva de una clase que
	contiene funciones virtuales, el compilador crea para cada clase
	una única VTABLE, que se puede ver a la derecha en el
	diagrama. En ésta tabla se colocan las direcciones de todas las
	funciones que son declaradas virtuales en la clase o en la clase
	base. Si no se sobreescribe una función que ha sido declarada
	como virtual, el compilador usa la dirección de la versión que
	se encuentra en la clase base (esto se puede ver en la entrada
	<literal>adjusta</literal> de la VTABLE de
	<classname>Brass</classname>). Además, se coloca el VPTR
	(descubierto en <filename>Sizes.cpp</filename>) en la clase. Hay
	un único VPTR por cada objeto cuando se usa herencia simple como
	es el caso. El VPTR debe estar inicializado para que apunte a la
	dirección inicial de la VTABLE apropiada (esto sucede en el
	constructor que se verá más tarde con mayor detalle).
      </para>

      <para>
	Una vez que el VPTR ha sido inicializado a la VTABLE apropiada,
	el objeto "sabe" de que tipo es. Pero este autoconocimiento no
	tiene valor a menos que sea usado en el momento en que se llama
	a la función virtual.
      </para>

      <para>
	Cuando se llama a una función virtual a través de la clase base
	(la situación que se da cuando el compilador no tiene toda la
	información necesaria para realizar la ligadura estática),
	ocurre algo especial. En vez de realizarse la típica llamada a
	función, que en lenguaje ensamblador es simplemente un
	<literal>CALL</literal> a una dirección en concreto, el
	compilador genera código diferente para ejecutar la llamada a la
	función. Aquí se muestra a lo que se parece una llamada a
	<function>adjust()</function> para un objeto
	<function>Brass</function>, si se hace a través de un puntero a
	<classname>Instrument</classname> (una referencia a
	<classname>Instrument</classname> produce el mismo efecto):
      </para>

      <figure>
	<title>Tabla de punteros virtuales</title>
	<mediaobject>
	  <imageobject role="latex">
	    <imagedata fileref="./images/V1_17.pdf" align="center" format="PDF"/>
	  </imageobject>
	  <imageobject role="html">
	    <imagedata fileref="./images/V1_17.png" align="center" format="PNG"/>
	  </imageobject>
	</mediaobject>
      </figure>

      <para>
	El compilador empieza con el puntero a
	<classname>Instrument</classname>, que apunta a la dirección
	inicial del objeto. Todos los objetos
	<classname>Instrument</classname> o los objetos derivados de
	<classname>Instrument</classname> tienen su VPTR en el mismo
	lugar (a menudo al principio del objeto), de tal forma que el
	compilador puede conseguir el VPTR del objeto. El VPTR apunta a
	la la dirección inicial de VTABLE. Todas las direcciones de
	funciones de las VTABLE están dispuestas en el mismo orden, a
	pesar del tipo específico del
	objeto. <function>play()</function> es el primero,
	<function>what()</function> es el segundo y
	<function>adjust()</function> es el tercero. El compilador sabe
	que a pesar del tipo específico del objeto, la función
	<function>adjust()</function> se encuentra localizada en
	VPTR+2. Debido a esto, en vez de decir, "Llama a la función en
	la dirección absoluta <function>Instrument::adjust()</function>
	(ligadura estática y acción equivocada), se genera código que
	dice "Llama a la función que se encuentre en VPTR+2". Como la
	búsqueda del VPTR y la determinación de la dirección de la
	función actual ocurre en tiempo de ejecución, se consigue la
	deseada ligadura dinámica. Se envía un mensaje al objeto, y el
	objeto se figura que debe hacer con él.
      </para>
    </sect2>

    <sect2>
      <title>Detrás del telón</title>

      <para>
	Puede ser útil ver el código ensamblador que se genera con la
	llamada a una función virtual, para poder ver como funciona la
	ligadura dinámica. Aquí está la salida de un compilador a la
	llamada
      </para>

<programlisting>
i.adjust(1);
</programlisting>

      <para>
	dentro de la función <literal>f(Instrument&amp; i)</literal>:
      </para>

<programlisting>
push 1
push si
mov  bx, word ptr [si]
call word ptr [bx+4]
add  sp, 4
</programlisting>

      <para>
	Los argumentos de una llamada a una función C++, como los de a
	una función C, son colocados en la pila de derecha a izquierda
	(este orden es necesario para poder soportar las listas de
	argumentos variables de C), por lo que el argumento
	<constant>1</constant> se pone al principio en la pila. En este
	punto en la función, el registro <varname>si</varname> (que es
	parte de la arquitectura del procesador
	<trademark>Intel</trademark> <productname>X86</productname>)
	contiene la dirección de <varname>i</varname>. También se
	introduce en la pila porque es la dirección de comienzo del
	objeto de interés. Hay que recordar que la dirección del
	comienzo del objeto corresponde al valor de
	<literal>this</literal>, y <literal>this</literal> es
	introducido en la pila de manera oculta antes de cualquier
	llamada a función, por lo que la función miembro sabe sobre qué
	objeto en concreto está trabajando. Debido a esto se verá
	siempre uno más que el número de argumentos introducidos en la
	pila antes de una llamada a una función miembro (excepto para
	las funciones miembro <kw>static</kw>, que no tienen
	<literal>this</literal>).
      </para>

      <para>
	Ahora se puede ejecutar la llamada a la función virtual. Primero
	hay que producir el VPTR para poder encontrar la VTABLE. Para el
	compilador el VPTR se inserta al principio del objeto, por lo
	que el contenido de <literal>this</literal> corresponde al
	VPTR. La línea
      </para>

<programlisting>
mov bx, word ptr [si]
</programlisting>

      <para>
	busca la dirección <emphasis>(word)</emphasis> a la que apunta
	<varname>si</varname>, que es el VPTR y la coloca dentro del
	registro <varname>bx</varname>.
      </para>

      <para>
	El VPTR contenido en <varname>bx</varname> apunta a la dirección
	inicial de la VTABLE, pero el puntero de la función a llamar no
	se encuentra en la posición cero de la VTABLE, si no en la
	segunda posición (debido a que es la tercera función en la
	lista). Debido al modelo de memoria cada puntero a función ocupa
	dos bytes, por lo que el compilador suma cuatro al VPTR para
	calcular donde está la dirección de la función apropiada. Hay
	que hacer notar que este es un valor constante establecido en
	tiempo de compilación, por lo que lo único que ocurre es que el
	puntero a función que está en la posición dos apunta a
	<function>adjust()</function>. Afortunadamente, el compilador se
	encarga de todo y se asegura de que todos los punteros a
	funciones en todas las VTABLEs de una jerarquía particular se
	creen con el mismo orden, a pesar del orden en que se hayan
	sobreescrito las funciones en las clases derivadas.
      </para>

      <para>
	Una vez se ha calculado en la VTABLE la dirección del puntero
	apropiado, se llama a la función a la que apunta el
	puntero. Esto es, se busca la dirección y se llama de una sola
	vez con la sentencia:
      </para>

<programlisting>
call word ptr [bx+4]
</programlisting>

      <para>
	Finalmente, se retrocede el puntero de la pila para limpiar los
	argumentos que se pusieron antes de la llamada. En código
	ensamblador de C y de C++ se ve a menudo la instrucción para
	limpiar la lista de argumentos pero puede variar dependiendo del
	procesador o de la implementación del compilador.
      </para>
    </sect2>

    <sect2>
      <title>Instalar el vpointer</title>

      <para>
	Debido a que el VPTR determina el comportamiento virtual de las
	funciones en un objeto, es crítico que el VPTR siempre esté
	apuntando a la VTABLE apropiada. No tendría sentido hacer una
	llamada a una función virtual antes de que esté inicializado
	apropiadamente a su correspondiente VTABLE. Por supuesto, el
	lugar donde se puede garantizar esta inicialización es en el
	constructor, pero ninguno de los ejemplos
	<classname>Instrument</classname> tiene constructor.
      </para>

      <para>
	Aquí es donde la creación del constructor por defecto es
	esencial. En los ejemplos <classname>Instrument</classname>, el
	compilador crea un constructor por defecto que no hace nada más
	que inicializar el VPTR. Este constructor es, obviamente,
	llamado autormáticamente por todos los objetos
	<classname>Instrument</classname> antes de que se pueda hacer nada
	con ellos, lo que asegura el buen comportamiento con las
	llamadas a funciones virtuales.
      </para>

      <para>
	Las implicaciones de la inicialización automática del VPTR
	dentro de un constructor se discute en un sección posterior.
      </para>
    </sect2>

    <sect2>
      <title>Los objetos son diferentes</title>

      <para>
	Es importante darse cuenta de que el
	<foreignphrase>upcasting</foreignphrase> sólo maneja
	direcciones. Si el compilador tiene un objeto, sabe su tipo
	concreto y además (en C++) no se usará la ligadura dinámica para
	ninguna de las llamadas a funciones - o como mínimo el
	compilador no <emphasis>necesitará</emphasis> usar la ligadura
	dinámica. Por cuestiones de eficiencia, la mayoría de los
	compiladores usarán la ligadura estática cuando esten haciendo
	una llamada a una función virtual de un objeto porque saben su
	tipo concreto. Aquí hay un ejemplo:
      </para>


//: V1C15:Early.cpp


      <para>
	En <literal>p1->speak()</literal> y en
	<literal>p2.speak()</literal>, se usan direcciones, lo que
	significa que la información es incompleta:
	<varname>p1</varname> y <varname>p2</varname> pueden representar
	la dirección de una <classname>Pet</classname> o algo que
	derivee de una <classname>Pet</classname>, por lo que el debe
	ser usado el mecanismo virtual. Cuando se llama a
	<literal>p3.speak</literal> no existe ambigüedad. El compilador
	conoce el tipo exacto del objeto, lo que hace imposible que sea
	un objeto derivado de <classname>Pet</classname> - es
	<emphasis>exactamente</emphasis> una
	<classname>Pet</classname>. Por esto, probablemente se use la
	ligadura estática. Sin embargo, si el compilador no quiere
	trabajar mucho, puede usar la ligadura dinámica y el
	comportamiento será el mismo.
      </para>
    </sect2>
  </sect1>

  <sect1>
    <title>¿Por qué funciones virtuales?</title>
    <para>
      A estas alturas usted se puede hacer una pregunta: "Si esta
      técnica es tan importante, y si se ejecuta la función
      <emphasis>correcta</emphasis> todo el tiempo, ¿por qué es una
      opción? ¿por qué es necesario conocerla?"
    </para>

    <para>
      Es una buena pregunta, y la respuesta se debe a la filosofía
      fudamental de C++: "Debido a que no es tan eficiente". Se puede
      ver en el código en lenguaje ensamblador que se generan, en vez de
      un simple <kw>CALL</kw> a una dirección absoluta, dos
      instrucciones ensamblador necesarias para preparar la llamada a
      función. Esto requiere más código y tiempo de ejecución.
    </para>

    <para>
      Algunos lenguajes orientado a objetos han decidido que la
      aproximación a la ligadura dinámica es intrínseca a la
      programación orientada a objetos, que siempre debe tener lugar,
      que no puede ser opcional, y que el usuario no tiene por qué
      conocerlo. Esta es una decisión de diseño cuando se crea un
      lenguaje, y éste camino particular es adecuado para varios
      lenguajes<footnote>
	<para>
	  Smalltalk, Java y Python, por ejemplo, usan esta aproximación
	  con gran éxito.
	</para>
      </footnote>.
      Sin embargo, C++ tiene una tara por venir
      de C, donde la eficiencia es crítica. Después de todo, C fué
      creado para sustituir al lenguaje ensamblador para la
      implementación de un sistema operativo (haciendo a este sistema
      operativo - Unix - mucho más portable que sus antecesores). Y una
      de las principales razones para la invención de C++ fue hacer más
      eficientes a los programadores de C<footnote>
	<para>
	  En los laboratorios Bell, donde se inventó C, hay <emphasis>un
	  montón</emphasis> de programadores de C. Hacerlos más
	  eficientes, aunque sea sólo un poco, ahorra a la compañía
	  muchos millones.
	</para>
      </footnote>. Y la primera pregunta cuando un programador de C se
      pasa a C++ es, "¿Cómo me afectará el cambio en velocidad y tamaño?
      Si la respuesta fuera, "Todo es magnífico excepto en las llamadas
      a funciones donde siempre tendrá un pequeña sobrecarga extra",
      mucha gente se hubiera aguantado con C antes que hacer el cambio a
      C++. Además las funciones inline no serían posibles, porque las
      funciones virtuales deben tener una dirección para meter en la
      VTABLE. Por lo tanto las funciones virtuales son opcionales,
      <emphasis>y</emphasis> por defecto el lenguaje no es
      <kw>virtual</kw>, porque es la configuración más
      eficiente. Stroustrup expuso que su línea de trabajo era, "Si no
      lo usa, no lo pague".
    </para>

    <para>
      Además la palabra reservada <kw>virtual</kw> permite
      afinar el rendimiento. Cuando se diseñan las clases, sin embargo,
      no hay que preocuparse por afinarlas. Si va a usar el
      polimorfismo, úselo en todos los sitios. Sólo es necesario buscar
      funciones que se puedan hacer no virtuales cuando se esté buscando
      modos de acelerar el código (y normalmente hay mucho más que ganar
      en otras áreas - una buena idea es intentar adivinar dónde se
      encuentran los cuellos de botella).
    </para>

    <para>
      Como anécdota la evidencia sugiere que el tamaño y la velocidad de
      C++ sufren un impacto del 10 por ciento con respecto a C, y a
      menudo están mucho más cerca de ser parejos. Además otra razón es
      que se puede diseñar un programa en C++ más rápido y más pequeño
      que como sería en C.
    </para>
  </sect1>


  <sect1>
    <!-- Abstract base classes and pure virtual functions -->
    <title>Clases base abstractas y funciones virtuales puras</title>

    <para>
      A menudo en el diseño, se quiere la clase base para presentar
      <emphasis>sólo</emphasis> una interfaz para sus clases
      derivadas. Esto es, se puede querer que nadie pueda crear un
      objeto de la clase base y que ésta sirva únicamente para hacer un
      <foreignphrase>upcast</foreignphrase> hacia ella, y poder tener
      una interfaz. Se consigue haciendo a la clase
      <foreignphrase>abstract</foreignphrase> (abstracta), poniendo como
      mínimo una <emphasis>función virtual pura</emphasis>. Se puede
      reconocer a una función virtual pura porque usa la palabra
      reservada <kw>virtual</kw> y es seguida por
      <literal>=0</literal>. Si alguien intenta hacer un objeto de una
      clase abstracta, el compilador lo impide. Esta es una utilidad que
      fuerza a un diseño en concreto.
    </para>

    <para>
      Cuando se hereda una clase abstracta, hay que implementar todas
      las funciones virtuales, o la clase que hereda se convierte en una
      nueva clase abstracta. Crear una función virtual pura permite
      poner una fución miembro en una interfaz sin forzar a proveer un
      cuerpo con código sin significado para esa función miembro. Al
      mismo tiempo, una función virtual fuerza a las clases que la
      hereden a que implemente una definición para ellas.
    </para>

    <para>
      En todos los ejemplos de los intrumentos, las funciones en la
      clase base <classname>Instrument</classname> eran siempre
      funciones <quote>tontas</quote>. Si esas funciones hubieran sido
      llamadas algo iba mal. Esto es porque la intención de la clase
      <classname>Instrument</classname> es crear una interfaz común
      para todas las clases que deriven de ella.
    </para>

    <figure>
      <title>Clase abstracta</title>
      <mediaobject>
	<imageobject role="latex">
	  <imagedata fileref="./images/V1_18.pdf" align="center" format="PDF"/>
	</imageobject>
	<imageobject role="html">
	  <imagedata fileref="./images/V1_18.png" align="center" format="PNG"/>
	</imageobject>
      </mediaobject>
    </figure>

    <para>
      La única razón para establecer una interfaz común es que después
      se pueda expresar de forma diferente en cada subtipo. Se crea una
      forma básica que tiene lo que está en común con todas las clases
      derivadas y nada más. Por esto, <classname>Instrument</classname> es
      un candidato perfecto para ser una clase abstracta. Se crea una
      clase abstracta sólo cuando se quiere manipular un conjunto de
      clases a través de una interfaz común, pero la interfaz común no
      necesita tener una implementación (o como mucho, no necesita una
      implementación completa).
    </para>

    <para>
      Si se tiene un concepto como <classname>Instrument</classname> que
      funciona como clase abstracta, los objetos de esa clase casi nunca
      tendrán sentido. Es decir, <classname>Instrument</classname> sirve
      solamente para expresar la interfaz, y no una implementación
      particular, por lo que crear un objeto que sea únicamente un
      <classname>Instrument</classname> no tendrá sentido, y
      probablemente se quiera prevenir al usuario de hacerlo. Se puede
      solucionar haciendo que todas las funciones virtuales en
      <classname>Instrument</classname> muestren mensajes de error, pero
      retrasa la aparición de los errores al tiempo de ejecución lo que
      obligará a un testeo exhaustivo por parte del usuario. Es mucho
      más productivo cazar el problema en tiempo de compilación.
    </para>

    <para>
      Aquí está la sintaxis usada para una función virtual pura:
    </para>

<programlisting>
virtual void f() = 0;
</programlisting>

    <para>
      Haciendo esto, se indica al compilador que reserve un hueco para
      una función en la VTABLE, pero que no ponga una dirección en ese
      hueco. Incluso aunque sólo una función en una clase sea declarada
      como virtual pura, la VTABLE estará incompleta.
    </para>

    <para>
      Si la VTABLE de una clase está incompleta, ¿qué se supone que debe
      hacer el compilador cuando alguien intente crear un objeto de esa
      clase? No sería seguro crear un objeto de esa clase abstracta, por
      lo que se obtendría un error de parte del compilador. Dicho de
      otra forma, el compilador garantiza la pureza de una clase
      abstracta. Hacer clases abstractas asegura que el programador
      cliente no puede hacer mal uso de ellas.
    </para>

    <para>
      Aquí tenemos <filename>Instrument4.cpp</filename> modificado para
      usar funciones virtuales puras. Debido a que la clase no tiene
      otra cosa que no sea funciones virtuales, se la llama
      <emphasis>clase abstracta pura</emphasis>:
    </para>


//: V1C15:Instrument5.cpp


    <para>
      Las funciones virtuales puras son útiles porque hacen explícita la
      abstracción de una clase e indican al usuario y al compilador cómo
      deben ser usadas.
    </para>

    <para>
      Hay que hacer notar que las funciones virtuales puras previenen a
      una clase abstracta de ser pasadas a una función <emphasis>por
      valor</emphasis>, lo que es una manera de prevenir el
      <foreignphrase>object slicing</foreignphrase> (que será descrito
      de forma reducida). Convertir una clase en abstracta también
      permite garantizar que se use siempre un puntero o una referencia
      cuando se haga <foreignphrase>upcasting</foreignphrase> a esa clase.
    </para>

    <para>
      Sólo porque una función virtual pura impida a la VTABLE estar
      completa no implica que no se quiera crear cuerpos de función para
      alguna de las otras funciones. A menudo se querrá llamar a la
      versión de la función que esté en la clase base, incluso aunque
      ésta sea virtual. Es una buena idea poner siempre el código común
      tan cerca como sea posible de la raiz de la jerarquía. No sólo
      ahorra código, si no que permite fácilmente la propagación de
      cambios.
    </para>

    <sect2>
      <title>Definiciones virtuales puras</title>

      <para>
	Es posible proveer una definición para una función virtual pura
	en la clase base. Todavía implica decirle al compilador que no
	permita crear objetos de esa clase base abstracta, y que las
	funciones virtuales puras deben ser definidas en las clases
	derivadas para poder crear objetos. Sin embargo, puede haber un
	trozo de código en común que se quiera llamar desde todas, o
	algunas de las clases derivadas en vez de estar duplicando
	código en todas las funciones.
      </para>

      <para>
	Este es un ejemplo de definición de funciones virtuales.
      </para>


//: V1C15:PureVirtualDefinitions.cpp


      <para>
	El hueco en la VTABLE de <classname>Pet</classname> todavía
	está vacío, pero tiene funciones a las que se puede llamar desde
	la clase derivada.
      </para>

      <para>
	Otra ventaja de esta característica es que perimite cambiar de
	una función virtual corriente a una virtual pura sin destrozar
	el código existente (es una forma para localizar clases que no
	sobreescriban a esa función virtual).
      </para>
    </sect2>
  </sect1>

  <sect1>
    <title>Herencia y la VTABLE</title>
    <para>
      Es fácil imaginar lo que sucede cuando hay herencia y se
      sobreescriben algunas de las funciones virtuales. El compilador
      crea una nueva VTABLE para la nueva clase, e inserta las nuevas
      direcciones de las funciones usando además las direcciones de las
      funciones de la clase base para aquellas funciones virtuales que
      no se hayan sobreescrito. De un modo u otro, para todos los
      objetos que se puedan crear (es decir, aquellos que no tengan
      funciones virtuales puras) existe un conjunto completo de
      direcciones de funciones en la VTABLE, por lo que será imposible
      hacer llamadas a una dirección que no esté en la VTABLE (lo cual
      sería desastroso).
    </para>

    <para>
      Pero ¿qué ocurre cuando se hereda y añade una nueva función
      virtual en la clase derivada? Aquí hay un sencillo ejemplo:
    </para>


//: V1C15:AddingVirtuals.cpp


    <para>
      La clase <classname>Pet</classname> tiene dos funciones
      virtuales: <function>speak()</function> y
      <function>name()</function>. <classname>Dog</classname> añade una
      tercera función virtual llamada <function>sit()</function>, y
      sobreescribe el significado de <function>speak()</function>. Un
      diagrama ayuda a visualizar qué está ocurriendo. Se muestran las
      VTABLEs creadas por el compilador para <classname>Pet</classname>
      y <classname>Dog</classname>:
    </para>

    <figure>
      <title>Una nueva función virtual</title>
      <mediaobject>
	<imageobject role="latex">
	  <imagedata fileref="./images/V1_19.pdf" align="center" format="PDF"/>
	</imageobject>
	<imageobject role="html">
	  <imagedata fileref="./images/V1_19.png" align="center" format="PNG"/>
	</imageobject>
      </mediaobject>
    </figure>

    <para>
      Hay que hacer notar, que el compilador mapea la dirección de
      <function>speak()</function> en exactamente el mismo lugar tanto
      en la VTABLE de <classname>Dog</classname> como en la de
      <classname>Pet</classname>. De igual forma, si una clase
      <classname>Pug</classname> heredara de <classname>Dog</classname>,
      su versión de <function>sit()</function> ocuparía su lugar en la
      VTABLE en la misma posición que en
      <classname>Dog</classname>. Esto es debido a que el compilador
      genera un código que usa un simple desplazamiento numérico en la
      VTABLE para seleccionar una función virtual, como se vio con el
      ejemplo en lenguaje ensamblador. Sin importar el subtipo en
      concreto del objeto, su VTABLE está colocada de la misma forma por
      lo que llamar a una función virtual se hará siempre del mismo
      modo.
    </para>

    <para>
      En este caso, sin embargo, el compilador está trabajando sólo con
      un puntero a un objeto de la clase base. La clase base tiene
      únicamente las funciones <function>speak()</function> y
      <function>name()</function>, por lo que son a las únicas funciones
      a las que el compilador permitirá acceder. ¿Cómo es posible saber
      que se está trabajando con un objeto <classname>Dog</classname> si
      sólo hay un puntero a un objeto de la clase base? El puntero
      podría apuntar a algún otro tipo, que no tenga una función
      <function>sit()</function>. En este punto, puede o no tener otra
      dirección a función en la VTABLE, pero en cualquiera de los casos,
      hacer una llamada a una función virtual de esa VTABLE no es lo que
      se desea hacer. De modo que el compilador hace su trabajo
      impidiendo hacer llamadas virtuales a funciones que sólo existen
      en las clases derivadas.
    </para>

    <para>
      Hay algunos poco comunes casos en los cuales se sabe que el
      puntero actualmente apunta al objeto de una subclase
      específica. Si se quiere hacer una llamada a una función que sólo
      exista en esa subclase, entonces hay que hacer un molde
      (<foreignphrase>cast</foreignphrase>) del puntero. Se puede quitar
      el mensaje de error producido por el anterior programa con:
    </para>

<programlisting>
((Dog *) p[1])->sit()
</programlisting>

    <para>
      Aquí, parece saberse que <literal>p[1]</literal> apunta a un
      objeto <classname>Dog</classname>, pero en general no se sabe. Si
      el problema consiste en averiguar el tipo exacto de todos los
      objetos, hay que volver a pensar porque posiblemente no se estén
      usando las funciones virtuales de forma apropiada. Sin embargo,
      hay algunas situaciones en las cuales el diseño funciona mejor (o
      no hay otra elección) si se conoce el tipo exacto de todos los
      objetos, por ejemplo aquellos incluidos en un contenedor
      genérico. Este es el problema de la <foreignphrase>run time type
      identification</foreignphrase> o RTTI (identificación de tipos en
      tiempo de ejecución).
    </para>

    <para>
      RTTI sirve para moldear un puntero de una clase base y "bajarlo" a
      un puntero de una clase derivada ("arriba" y "abajo", en inglés
      "up" y "down" respectivamente, se refieren al típico diagrama de
      clases, con la clase base arriba). Hacer el molde hacia arriba
      (<foreignphrase>upcast</foreignphrase>) funciona de forma
      automática, sin coacciones, debido a que es completamente
      seguro. Hacer el molde en sentido descendente
      (<foreignphrase>downcast</foreignphrase>) es inseguro porque no
      hay información en tiempo de compilación sobre los tipos actuales,
      por lo que hay que saber exactamente el tipo al que pertenece. Si
      se hace un molde al tipo equivocado habrá problemas.
    </para>

    <para>
      RTTI se describe posteriormente en este capítulo, y el Volumen 2
      de este libro tiene un capítulo dedicado al tema.
    </para>

    <sect2>
      <title>FIXME: Object slicing</title>

      <para>
	Existe una gran diferencia entre pasar una dirección de un
	objeto a pasar el objeto por valor cuando se usa el
	polimorfismo. Todos los ejemplos que se han visto, y
	prácticamente todos los ejemplos que se verán, se pasan por
	referencia y no por valor. Esto se debe a que todas las
	direcciones tienen el mismo tamaño<footnote>
	  <para>
	    Actualmente, no todos los punteros tienen el mismo tamaño en
	    todos las máquinas. Sin embargo, en el contexto de esta
	    discusión se pueden considerar iguales.
	  </para>
	</footnote>, por lo que pasar
	la dirección de un tipo derivado (que normalmente será un objeto
	más grande) es lo mismo que pasar la dirección de un objeto del
	tipo base (que es normalmente más pequeño). Como se explicó
	anteriormente, éste es el objetivo cuando se usa el polimorfismo
	- el código que maneja un tipo base puede, también manejar
	objetos derivados de forma transparente
      </para>

      <para>
	Si se hace un <foreignphrase>upcast</foreignphrase> de un objeto
	en vez de usar un puntero o una referencia, pasará algo que
	puede resultar sorprendente: el objeto es "truncado", recortado,
	hasta que lo que quede sea un subobjeto que corresponda al tipo
	destino del molde. En el siguiente ejemplo se puede ver que
	ocurre cuando un objeto es truncado (<foreignphrase>object
	slicing</foreignphrase>):
      </para>


//: V1C15:ObjectSlicing.cpp


      <para>
	La función <function>describe()</function> recibe un objeto de
	tipo <classname>Pet</classname> <emphasis>por valor</emphasis>.
	Después llama a la función virtual
	<function>description()</function> del objeto
	<classname>Pet</classname>. En el <function>main()</function>,
	se puede esperar que la primera llamada produzca "This is
	Alfred", y que la segunda produzca "Fluffy likes to
	sleep". De hecho, ambas usan la versión
	<function>description()</function> de la clase base.
      </para>

      <para>
	En este programa están sucediendo dos cosas. Primero, debido a
	que <function>describe()</function> acepta un objeto
	<classname>Pet</classname> (en vez de un puntero o una
	referencia), cualquier llamada a <function>describe()</function>
	creará un objeto del tamaño de <classname>Pet</classname> que
	será puesto en la pila y posteriormente limpiado cuando acabe la
	llamada. Esto significa que si se pasa a
	<function>describe()</function>un objeto de una clase heredada
	de <classname>Pet</classname>, el compilador lo acepta, pero
	copia únicamente el fragmento del objeto que corresponda a una
	<classname>Pet</classname>. Se deshecha el fragmento derivado
	del objeto:
      </para>

      <figure>
	<title>Object slicing</title>
	<mediaobject>
	  <imageobject role="latex">
	    <imagedata fileref="./images/V1_20.pdf" align="center" format="PDF"/>
	  </imageobject>
	  <imageobject role="html">
	    <imagedata fileref="./images/V1_20.png" align="center" format="PNG"/>
	  </imageobject>
	</mediaobject>
      </figure>

      <para>
	Ahora queda la cuestión de la llamada a la función
	virtual. <function>Dog::description()</function> hace uso de
	trozos de <classname>Pet</classname> (que todavía existe) y de
	<classname>Dog</classname>, ¡el cual no existe porque fue
	truncado!. Entonces, ¿Qué ocurre cuando se llama a la función
	virtual?
      </para>

      <para>
	El desastre es evitado porque el objeto es pasado por
	valor. Debido a esto, el compilador conoce el tipo exacto del
	objeto porque el objeto derivado ha sido forzado a transformarse
	en un objeto de la clase base. Cuando se pasa por valor, se usa
	el constructor de copia del objeto <classname>Pet</classname>,
	que se encarga de inicializar el VPTR a la VTABLE de
	<classname>Pet</classname> y copia sólo las partes del objeto
	que correspondan a <classname>Pet</classname>. En el ejemplo no
	hay un constructor de copia explícito por lo que el compilador
	genera uno. Quitando interpretaciones, el objeto se convierte
	realmente en una <classname>Pet</classname> durante el
	truncado.
      </para>

      <para>
	El <foreignphrase>Object Slicing</foreignphrase> quita parte del
	objeto existente y se copia en un nuevo objeto, en vez de
	simplemente cambiar el significado de una dirección cuando se
	usa un puntero o una referencia. Debido a esto, el
	<foreignphrase>upcasting</foreignphrase> a un objeto no se usa a
	menudo; de hecho, normalmente, es algo a controlar y
	prevenir. Hay que resaltar que en este ejemplo, si
	<function>description()</function> fuera una función virtual
	pura en la clase base (lo cual es bastante razonable debido a
	que realmente no hace nada en la clase base), entonces el
	compilador impedirá el <foreignphrase>object
	slicing</foreignphrase> debido a que no se puede "crear" un
	objeto de la clase base (que al fin y al cabo es lo que sucede
	cuando se hace un upcast por valor). ésto podría ser el valor
	más importante de las funciones virtuales puras: prevenir el
	<foreignphrase>object slicing</foreignphrase> generando un error
	en tiempo de compilación si alguien lo intenta hacer.
      </para>
    </sect2>
  </sect1>

  <!--
      <notapie>
  <negrita>Object slicing </negrita> N del T: Otro término molesto de
  díficil traducción y sin embargo sencillo como concepto. Quizá fuera
  aceptable algo así como "truncar el objeto", pero prefiero dejarlo en
  el idioma original hasta que se encuentre otra alternativa mejor. Por
  desgracia otro tanto para los de Shaskespeare.<intro></intro>
  <negrita>8</negrita>:
</notapie>
  -->

  <sect1>
    <title>Sobrecargar y redefinir</title>

    <para>
      En el capítulo 14 se vio que redefinir una función sobrecargada en
      la función base oculta todas las otras versiones de esa
      función. Cuando se involucra a las funciones virtuales el
      comportamiento es un poco diferente. Consideremos una versión
      modificada del ejemplo <filename>NameHiding.cpp</filename> del
      capítulo 14:
    </para>


//: V1C15:NameHiding2.cpp


    <para>
      La primera cosa a resaltar es que en
      <classname>Derived3</classname>, el compilador no permitirá
      cambiar el tipo de retorno de una función sobreescrita (lo
      permitiría si <function>f()</function> no fuera virtual). ésta es
      una restricción importante porque el compilador debe garantizar
      que se pueda llamar de forma "polimórfica" a la función a través
      de la clase base, y si la clase base está esperando que
      <function>f()</function> devuelva un <type>int</type>,
      entonces la versión de <function>f()</function> de la clase
      derivada debe mantener ese compromiso o si no algo fallará.
    </para>

    <para>
      La regla que se enseño en el capítulo 14 todavía funciona: si se
      sobreescribe una de las funciones miembro sobrecargadas de la
      clase base, las otras versiones sobrecargadas estarán ocultas en
      la clase derivada. En el <function>main()</function> el código de
      <classname>Derived4</classname> muestra lo que ocurre incluso si la
      nueva versión de <function>f()</function> no está actualmente
      sobreescribiendo una función virtual existente de la interfaz -
      ambas versiones de <function>f()</function> en la clase base estan
      ocultas por <function>f(int)</function>. Sin embargo, si se hace un
      upcast de <varname>d4</varname> a <classname>Base</classname>,
      entonces únicamente las versiones de la clase base estarán
      disponibles (porque es el compromiso de la clase base) y la
      versión de la clase derivada no está disponible (debido a que no
      está especificada en la clase base).
    </para>

    <sect2>
      <title>Tipo de retorno variante</title>

      <para>
	La clase <classname>Derived3</classname> de arriba viene a sugerir
	que no se puede modificar el tipo de retorno de una función
	virtual cuando es sobreescrita. En general es verdad, pero hay
	un caso especial en el que se puede modificar ligeramente el
	tipo de retorno. Si se está devolviendo un puntero o una
	referencia a una clase base, entonces la versión sobreescrita de
	la función puede devolver un puntero o una referencia a una
	clase derivada. Por ejemplo:
      </para>


//: V1C15:VariantReturn.cpp


      <para>
	La función miembro <function>Pet::eats()</function> devuelve un
	puntero a <classname>PetFood</classname>. En
	<classname>Bird</classname>, ésta función miembro es
	sobreescrita exactamente como en la clase base, incluyendo el
	tipo de retorno. Esto es, <function>Bird::eats()</function> hace
	un <foreignphrase>>upcast</foreignphrase> de
	<classname>BirdFood</classname> a <classname>PetFood</classname>
	en el retorno de la función.
      </para>

      <para>
	Pero en <classname>Cat</classname>, el tipo devuelto por
	<function>eats()</function> es un puntero a
	<classname>CatFood</classname>, que es un tipo derivado de
	<classname>PetFood</classname>. El hecho de que el tipo de
	retorno esté heredado del tipo de retorno la función de la clase
	base es la única razón que hace que esto compile. De esta forma
	el acuerdo se cumple totalmente: <function>eats()</function>
	siempre devuelve un puntero a <classname>PetFood</classname>.
      </para>

      <para>
	Si se piensa de forma polimórfica lo anterior no parece
	necesario. ¿Por qué no simplemente se hacen upcast de todos los
	tipos retornados a <type>PetFood*</type> como lo hace
	<function>Bird::eats()</function>? Normalmente esa es una buena
	solución, pero al final del <function>main()</function> se puede
	ver la diferencia: <function>Cat::eats()</function> puede
	devolver el tipo exacto de <classname>PetFood</classname>,
	mientras que al valor retornado por
	<function>Bird::eats()</function> hay que hacerle
	un <foreignphrase>downcast</foreignphrase> al
	tipo exacto.
      </para>

      <para>
	Devolver el tipo exacto es un poco más general y además no
	pierde la información específica de tipo debida al upcast
	automático. Sin embargo, devolver un tipo de la clase base
	generalmente resuelve el problema por lo que esto es una
	característica bastante específica.
      </para>
    </sect2>
  </sect1>

  <sect1>
    <title>funciones virtuales y constructores</title>

    <para>
      Cuando se crea un objeto que contiene funciones virtuales, su VPTR
      debe ser inicializado para apuntar a la correcta VTABLE. Esto debe
      ser hecho antes de que exista la oportunidad de llamar a una
      función virtual. Como se puede adivinar, debido a que el
      constructor tiene el trabajo de traer a la existencia al objeto,
      también será trabajo del constructor inicializar el VPTR. El
      compilador de forma secreta añade código al principio del
      constructor para inicializar el VPTR. Y como se describe en el
      capítulo 14, si no se crea un constructor de una clase de forma
      explícita, el compilador genera uno de forma automática. Si la
      clase tiene funciones virtuales, el constructor incluirá el código
      apropidado para la inicialización del VPTR. Esto tiene varias
      consecuencias.
    </para>

    <para>
      La primera concierne a la eficiencia. La razón de que existan
      funciones <kw>inline</kw> es reducir la sobrecarga que
      produce llamar a funciones pequeñas. Si C++ no proporciona
      funciones <kw>inline</kw>, el preprocesador debe ser
      usado para crear estas "macros". Sin embargo, el preprocesador no
      tiene los conceptos de accesos o clases, y además no puede ser
      usado para crear macros con funciones miembro. Además, con los
      constructores que deben tener código oculto insertado por el
      compilador, una macro del preprocesador no funcionaría del todo.
    </para>

    <para>
      Hay que estar precavidos cuando se estén buscando agujeros de
      eficiencia porque el compilador está insertando código oculto en
      los constructores. No sólo hay que inicializar el VPTR, también
      hay que comprobar el valor de <literal>this</literal> (en caso de
      que el operador <kw>new</kw> devuelva cero), y llamar
      al constructor de la clase base. Todo junto, éste código puede
      tener cierto impacto cuando se pensaba que era una simple función
      <kw>inline</kw>. En particular, el tamaño del
      constructor puede aplastar al ahorro que se consigue al reducir la
      sobrecarga en las llamadas. Si se hacen un monton de llamadas a
      constructores inline, el tamaño del código puede crecer sin ningún
      beneficio en la velocidad.
    </para>

    <para>
      Cuando esté afinando el código recuerde considerar el quitar los
      constructores en línea.
    </para>

    <sect2>
      <title>Orden de las llamadas a los constructores</title>

      <para>
	La segunda faceta interesante de los constructores y las
	funciones virtuales tiene que ver con el orden de las llamadas a
	los constructores y el modo en que las llamadas virtuales se
	hacen dentro de los constructores.
      </para>

      <para>
	Todos los constructores de la clase base son siempre llamados en
	el constructor de una clase heredada. Esto tiene sentido porque
	el constructor tiene un trabajo especial: ver que el objeto está
	construido de forma apropiada. Una clase derivada sólo tiene
	acceso a sus propios miembros, y no a los de la clase
	base. únicamente el constructor de la clase base puede
	inicializar de forma adecuada a sus propios elementos. Por lo
	tanto es esencial que se llame a todos los constructores; de
	otra forma el objeto no estará construido de forma
	adecuada. Esto es por lo que el compilador obliga a hacer una
	llamada por cada trozo en una clase derivada. Se llamará al
	constructor por defecto si no se hace una llamada explícita a un
	constructor de la clase base. Si no existe constructor por
	defecto, el compilador lo creará.
      </para>

      <para>
	El orden de las llamadas al constructor es importante. Cuando se
	hereda, se sabe todo sobre la clase base y se puede acceder a
	todos los miembros públicos y protegidos
	(<kw>public</kw> y <kw>protected</kw>) de la
	clase base. ésto significa que se puede asumir que todos los
	miembros de la clase base son válidos cuando se está en la clase
	derivada. En una función miembro normal, la construcción ya ha
	ocurrido, por lo que todos los miembros de todas las partes del
	objeto ya han sido construidos. Dentro del constructor, sin
	embargo, hay que asumir que todos los miembros que se usen han
	sido construidos. La única manera de garantizarlo es llamando
	primero al constructor de la clase base. Entonces cuando se esté
	en el constructor de la clase derivada, todos los miembros a los
	que se pueda acceder en la clase base han sido
	inicializados. "Saber que todos los miembros son válidos" dentro
	del constructor es también la razón por la que, dentro de lo
	posible, se debe inicializar todos los objetos miembros (es
	decir, los objetos puestos en la clase mediante composición). Si
	se sigue ésta práctica, se puede asumir que todos los miembros
	de la clase base y los miembros objetos del objeto actual han
	sido inicializados.
      </para>
    </sect2>

    <sect2>
      <title>Comportamiento de las funciones virtuales dentro de los
      constructores</title>

      <para>
	La jerarquía de las llamadas a los constructores plantea un
	interesante dilema. ¿Qué ocurre si se está dentro de un
	constructor y se llama a una función virtual? Dentro de una
	función miembro ordinaria se puede imaginar que ocurrirá - la
	llamada virtual es resuelta en tiempo de ejecución porque el
	objeto no puede conocer si la función miembro es de la clase en
	la que está o es de una clase derivada. Por consistencia, se
	podría pensar que también es lo que debería ocurrir dentro de
	los constructores.
      </para>

      <para>
	No es el caso. Si se llama a una función virtual dentro de un
	constructor, sólo se usa la versión local de la función. Es
	decir, el mecanismo virtual no funciona dentro del constructor.
      </para>

      <para>
	éste comportamiento tiene sentido por dos
	motivos. Conceptualmente, el trabajo del constructor es dar al
	objeto una <emphasis>existencia</emphasis>. Dentro de cualquier
	constructor, el objeto puede ser formado sólo parcialmente - se
	puede saber sólo que los objetos de la clase base han sido
	inicializados, pero no se puede saber que clases heredan de
	ésta. Una función virtual, sin embargo, se mueve "arriba" y
	"abajo" dentro de la jerarquía de herencia. Llama a una función
	de una clase derivada. Si se pudiera hacer esto dentro de un
	constructor, se estaría llamando a una función que debe manejar
	miembros que todavía no han sido inicializados, una receta
	segura para el desastre.
      </para>

      <para>
	El segundo motivo es mecánico. Cuando se llama a un constructor,
	una de las primeras cosas que hace es inicializar su VPTR. Sin
	embargo, sólo puede saber que es del tipo "actual" - el tipo
	para el que se ha escrito el constructor. El código del
	constructor ignora completamente si el objeto está en la base de
	otra clase. Cuando el compilador genera código para ese
	constructor, se genera código para un constructor de esa clase,
	no para la clase base, ni para una clase derivada (debido a que
	una clase no puede saber quién la hereda). Por eso, el VPTR que
	use debe apuntar a la VTABLE de <emphasis>esa</emphasis> clase. El
	VPTR permanece inicializado a la VTABLE para el resto de vida
	del objeto a menos que no sea la última llamada al
	constructor. Si posteriormente se llama a un constructor de una
	clase derivada, éste constructor pone el VPTR a
	<emphasis>su</emphasis> VTABLE, y así hasta que el último
	constructor termine. El estado del VPTR es determinado por el
	constructor que sea llamado en último lugar. Otra razón por la
	que los constructores son llamados en orden desde la base al más
	derivado.
      </para>

      <para>
	Pero mientras que toda esta serie de llamadas al constructor
	tiene lugar, cada constructor ha puesto el VPTR a su propia
	VTABLE. Si se usa el mecanismo virtual para llamar a funciones,
	producirá sólo una llamada a través de su propia VTABLE, y no de
	la VTABLE del más derivado (como debería suceder después de que
	todos los constructores hayan sido llamados). Además, muchos
	compiladores reconocen cuando se hace una llamada a una función
	virtual dentro de un constructor, y realizan una ligadura
	estática porque saben que la ligadura dinámica producirá una
	llamada a una función local. En todo caso, no se conseguirán los
	resultados que se podían esperar inicialmente de la llamada a
	una función virtual dentro de un constructor.
      </para>
    </sect2>

    <sect2>
      <title>Destructores y destructores virtuales</title>

      <para>
	No se puede usar la palabra reservada
	<kw>virtual</kw> con los constructores, pero los
	destructores pueden, y a menudo deben, ser virtuales.
      </para>

      <para>
	El constructor tiene el trabajo especial de iniciar un objeto
	poco a poco, primero llamando al constructor base y después a
	los constructores derivados en el orden de la herencia. De
	manera similar, el destructor tiene otro trabajo especial:
	desmontar un objeto, el cual puede pertenecer a una jerarquía de
	clases. Para hacerlo, el compilador genera código que llama a
	todos los destructores, pero en el orden
	<emphasis>inverso</emphasis> al que son llamados en los
	constructores. Es decir, el constructor empieza en la clase más
	derivada y termina en la clase base. ésta es la opción deseable
	y segura debido a que el destructor siempre sabe que los
	miembros de la clase base están vivos y activos. Si se necesita
	llamar a una función miembro de la clase base dentro del
	destructor, será seguro hacerlo. De esta forma, el destructor
	puede realizar su propio limpiado, y entonces llamar al
	siguiente destructor, el cual hará <emphasis>su</emphasis> propio
	limpiado, etc. Cada destructor sabe de que clase deriva, pero no
	cuales derivan de él.
      </para>

      <para>
	Hay que tener en cuenta que los constructores y los destructores
	son los únicos lugares donde tiene que funcionar ésta jerarquía
	de llamadas (que es automáticamente generada por el
	compilador). En el resto de las funciones, sólo esa función, sea
	o no virtual, será llamada (y no las versiones de la clase
	base). La única forma para acceder a las versiones de la clase
	base de una función consiste en llamar de forma
	<emphasis>explicita</emphasis> a esa funciones.
      </para>

      <para>
	Normalmente, la acción del destructor es adecuada. Pero ¿qué
	ocurre si se quiere manipular un objeto a través de un puntero a
	su clase base (es decir, manipular al objeto a través de su
	interfaz genérica)? Este tipo de actividades es uno de los
	objetivos de la programación orientada a objetos. El problema
	viene cuando se quiere hacer un <kw>delete</kw>
	(eliminar) de un puntero a un objeto que ha sido creado en el
	<emphasis>montón</emphasis>
	(<foreignphrase>>heap</foreignphrase>) con
	<kw>new</kw>. Si el puntero apunta a la clase base, el
	compilador sólo puede conocer la versión del destructor que se
	encuentre en la clase base durante el
	<kw>delete</kw>. ¿Suena familiar? Al fin y al cabo, es
	el mismo problema por las que fueron creadas las funciones
	virtuales en el caso general. Afortunadamente, las funciones
	virtuales funcionan con los destructores como lo hacen para las
	otras funciones excepto los constructores.
      </para>


//: V1C15:VirtualDestructors.cpp


      <para>
	Cuando se ejecuta el programa, se ve que <literal>delete
	bp</literal> sólo llama al destructor de la clase base, mientras
	que <literal>delete b2p</literal> llama al destructor de la
	clase derivada seguido por el destructor de la clase base, que
	es el comportamiento que deseamos. Olvidar hacer
	<kw>virtual</kw> a un destructor es un error
	peligroso porque a menudo no afecta directamente al
	comportamiento del programa, pero puede introducir de forma
	oculta agujeros de memoria. Además, el hecho de que
	<emphasis>alguna</emphasis> destrucción está teniendo lugar puede
	enmascarar el problema.
      </para>

      <para>
	Es posible que el destructor sea virtual porque el objeto sabe
	de que tipo es (lo que no ocurre durante la construcción del
	objeto). Una vez que el objeto ha sido construido, su VPTR es
	inicializado y se pueden usar las funciones virtuales.
      </para>
    </sect2>

    <sect2>
      <title>Destructores virtuales puros</title>

      <para>
	Mientras que los destructores virtuales puros son legales en el
	Standard C++, hay una restricción añadida cuando se usan: hay
	que proveer de un cuerpo de función a los destructores virtuales
	puros. Esto parece antinatural; ¿Cómo puede una función virtual
	ser "pura" si necesita el cuerpo de una función? Pero si se
	tiene en cuenta que los constructores y los destructores son
	operaciones especiales tiene más sentido, especialmente si se
	recuerda que todos los destructores en una jerarquía de clases
	son llamados siempre. Si se quita la definición de un destructor
	virtual puro, ¿a qué cuerpo de función se llamará durante la
	destrucción? Por esto, es absolutamente necesario que el
	compilador y el enlazador requieran la existencia del cuerpo de
	una función para un destructor virtual puro.
      </para>

      <para>
	Si es puro, pero la función tiene cuerpo ¿cuál es su valor? La
	única diferencia que se verá entre el destructor virtual puro y
	el no-puro es que el destructor virtual puro convierte a la
	clase base en abstracta, por lo que no se puede crear un objeto
	de la clase base (aunque esto también sería verdad si cualquier
	otra función miembro de esa clase base fuera virtual pura).
      </para>

      <para>
	Sin embargo, las cosas son un poco confusas cuando se hereda una
	clase de otra que contenga un destructor puro virtual. Al
	contrario que en el resto de las funciones virtuales puras,
	<emphasis>no</emphasis> es necesario dar una definición de un
	destructor virtual puro en la clase derivada. El hecho de que el
	siguiente código compile es la prueba:
      </para>


//: V1C15:UnAbstract.cpp


      <para>
	Normalmente, una función virtual pura en una clase base causará
	que la clase derivada sea abstracta a menos que esa (y todas las
	demás funciones virtuales puras) tengan una definición. Pero
	aquí, no parece ser el caso. Sin embargo, hay que recordar que
	el compilador crea <emphasis>automáticamente</emphasis> una
	definición del destructor en todas las clases si no se crea una
	de forma explícita. Esto es lo que sucede aquí - el destructor
	de la clase base es sobreescrito de forma oculta, y una
	definición es puesta por el compilador por lo que
	<classname>Derived</classname> no es abstracta.
      </para>

      <para>
	Esto nos brinda una cuestión interesante: ¿Cuál es el sentido de
	un destructor virtual puro? Al contrario que con las funciones
	virtuales puras ordinarias en las que hay que
	<emphasis>dar</emphasis> el cuerpo de una función, en una clase
	derivada de otra con un destructor virtual puro, no se está
	obligado a implementar el cuerpo de la función porque el
	compilador genera automáticamente el destructor. Entonces ¿Cuál
	es la diferencia entre un destructor virtual normal y un
	destructor virtual puro?
      </para>

      <para>
	La única diferencia ocurre cuando se tiene una clase que sólo
	tiene una función virtual pura: el destructor. En este caso, el
	único efecto de la <emphasis>pureza</emphasis> del destructor es
	prevenir la instanciación de la clase base, pero si no existen
	otros destructores en las clase heredadas, el destructor virtual
	se ejecutará. Por esto, mientras que el añadir un destructor
	virtual es esencial, el hecho de que sea puro o no lo sea no es
	tan importante.
      </para>

      <para>
	Cuando se ejecuta el siguiente ejemplo, se puede ver que se
	llama al cuerpo de la función virtual pura después de la versión
	que está en la clase derivada, igual que con cualquier otro
	destructor.
      </para>



//: V1C15:PureVirtualDestructors.cpp



      <para>
	Como guía, cada vez que se tenga una función virtual en una
	clase, se debería añadir inmediatamente un destructor virtual
	(aunque no haga nada). De esta forma se evitan posteriores
	sorpresas.
      </para>
    </sect2>

    <sect2>
      <title>Mecanismo virtual en los destructores</title>

      <para>
	Hay algo que sucede durante la destrucción que no se espera de
	manera intuitiva. Si se está dentro de una función miembro y se
	llama a una función virtual, esa función es ejecutada usando el
	mecanismo de la ligadura dinámica. Esto no es verdad con los
	destructores, virtuales o no. Dentro de un destructor, sólo se
	llama a la función miembro "local"; el mecanismo virtual es
	ignorado.
      </para>


//: V1C15:VirtualsInDestructors.cpp



      <para>
	Durante la llamada al destructor virtual, no se llama a
	<function>Derived::f()</function>, incluso aunque
	<function>f()</function> es virtual.
      </para>

      <para>
	¿A qué es debido ésto? Supongamos que fuera usado el mecanismo
	virtual dentro del destructor. Entonces sería posible para la
	llamada virtual resolver una función que está "lejana" (más
	derivada) en la jerarquía de herencia que el destructor
	actual. Pero los destructores son llamados de "afuera a dentro"
	(desde el destructor más derivado hacia el destructor de la
	clase base), por lo que la llamada actual a la función puede
	intentar acceder a fragmentos de un objeto que <emphasis>!ya ha
	sido destruido!</emphasis> En vez de eso, el compilador resuelve
	la llamada en tiempo de compilación y llama sólo a la versión
	local de la función. Hay que resaltar que lo mismo es también
	verdad para el constructor (como se explicó anteriormente), pero
	en el caso del constructor el tipo de información no estaba
	disponible, mientras que en el destructor la información está
	ahí (es decir, el VPTR) pero no es accesible.
      </para>
    </sect2>

    <sect2>
      <title>Creación una jerarquía basada en objetos</title>

      <para>
	Un asunto que ha aparecido de forma recurrente a lo largo de
	todo el libro cuando se usaban las clases
	<classname>Stack</classname> y <classname>Stash</classname> es
	el "problema de la propiedad". El "propietario" se refiere a
	quien o al que sea responsable de llamar al
	<kw>delete</kw> de aquellos objetos que hayan sido
	creados dinámicamente (usando <kw>new</kw>). El
	problema cuando se usan contenedores es que es necesario ser lo
	suficientemente flexible para manejar distintos tipos de
	objetos. Para conseguirlo, los contenedores manejan punteros a
	<type>void</type> por lo que no pueden saber el tipo del
	objeto que están manejando. Borrar un puntero a
	<type>void</type> no llama al destructor, por lo que el
	contenedor no puede ser responsable de borrar sus objetos.
      </para>

      <para>
	Una solución fue presentada en el ejemplo
	<filename>C14:InheritStack.cpp</filename>, en el que
	<classname>Stack</classname> era heredado en una nueva clase que
	aceptaba y producía únicamente objetos
	<type>string</type>, por lo que se les podía borrar de
	manera adecuada. Era una buena solución pero requería heredar
	una nueva clase contenedera por cada tipo que se quisiera
	manejar en el contenedor. (Aunque suene un poco tedioso funciona
	bastante bien como se verá en el capítulo 16 cuando las
	plantillas o templates sean introducidos).
      </para>

      <para>
	El problema es que se quiere que el contenedor maneje más de un
	tipo, pero sólo se quieren usar punteros a
	<type>void</type>. Otra solución es usar polimorfismo
	forzando a todos los objetos incluidos en el contenedor a ser
	heredados de la misma clase base. Es decir, el contenedor maneja
	los objetos de la clase base, y sólo hay que usar funciones
	virtuales - en particular, se pueden llamar a destructores
	virtuales para solucionar el problema de pertenencia.
      </para>

      <para>
	Esta solución usa lo que se conoce como "jerarquía de raiz
	única" (<foreignphrase>singly-rooted hierarchy</foreignphrase>)
	o "jerarquía basada en objetos" (<foreignphrase>object-based
	hierarchy</foreignphrase>), siendo el último nombre debido a que la
	clase raiz de la jerarquía suele ser llamada "Objeto". Además,
	el usar jerarquía de raiz única, tiene como resultado otros
	beneficios: de hecho, cualquier otro lenguaje orientado a
	objetos que no sea el C++ obliga a usar una jerarquía - cuando
	se crea una clase se hereda automáticamente de forma directa o
	indirecta de una clase base común, una clase base que fue
	establecida por los creadores del lenguaje. En C++, se penso que
	forzar a tener una base clase común crearía demasiada
	sobrecarga, por lo que se desestimó. Sin embargo, se puede
	elegir usar en nuestros proyectos una clase base común, y esta
	materia será tratada en el segundo volumen de este libro.
      </para>

      <para>
	Para solucionar el problema de pertenencia, se puede crear una
	clase base <classname>Object</classname> extremadamente simple,
	que sólo tiene un destructor virtual. De esta forma
	<classname>Stack</classname> puede manejar objetos que hereden
	de <classname>Object</classname>:
      </para>


//: V1C15:OStack.h"/>


      <para>
	Para simplificar las cosas se crea todo en el fichero cabecera,
	la definición (requerida) del destructor virtual puro es
	introducida en línea el el fichero cabecera, y
	<function>pop()</function> también está en línea aunque podría
	ser considearado como demasiado largo para ser incluido así.
      </para>

      <para>
	Los objetos <classname>Link</classname> (lista) ahora manejan
	punteros a <classname>Object</classname> en vez de punteros a
	<type>void</type>, y la <classname>Stack</classname> (pila) sólo
	aceptará y devolverá punteros a
	<classname>Object</classname>. Ahora
	<classname>Stack</classname> es mucho más flexible, ya que puede
	manejar un montón de tipos diferentes pero además es capaz de
	destruirá cualquier objeto dejado en la pila. La nueva
	limitación (que será finalmente eliminada cuando las plantillas
	se apliquen al problema en el capítulo 16) es que todo lo que se
	ponga en la pila debe ser heredado de
	<classname>Object</classname>. Esto está bien si se crea una clase
	desde la nada, pero ¿qué pasa si se tiene una clase como
	<classname>string</classname> y se quiere ser capaz de meterla en
	la pila? En este caso, la nueva clase debe ser al mismo tiempo
	un <classname>string</classname> y un <classname>Object</classname>, lo
	que significa que debe heredar de ambas clases. Esto se conoce
	como <emphasis>herencia múltiple</emphasis> y es materia para un
	capítulo entero en el Volumen 2 de este libro (se puede bajar de
	www.BruceEckel.com). cuando se lea este capítulo, se verá que la
	herencia múltiple genera un montón de complejidad, y que es una
	característica que hay que usar con cuentagotas. Sin embargo,
	ésta situación es lo suficiéntemente simple como para no tener
	problemas al usar herencia múltiple:
      </para>


//: V1C15:OStackTest.cpp


      <para>
	Aunque es similar a la versión anterior del programa de pruebas
	de <classname>Stack</classname>, se puede ver que sólo se han
	sacado 10 elementos de la pila, lo que implica que probablemente
	quede algún elemento. Como la pila ahora maneja
	<classname>Object</classname>s, el destructor puede limpiarlos
	de forma adecuada, como se puede ver en la salida del programa
	gracias a que los objetos <classname>MyString</classname>
	muestran un mensaje cuando son destruidos.
      </para>

      <para>
	Crear contenedores que manejen <classname>Object</classname>s es
	una aproximación razonable - si se tiene una jerarquía de raiz
	única (debido al lenguaje o por algún requerimiento que obligue
	a que todas las clases hereden de
	<classname>Object</classname>). En este caso, está garantizado
	que todo es un <classname>Object</classname> y no es muy
	complicado usar contenedores. Sin embargo, en C++ no se puede
	esperar este comportamiento de todas las clases, por lo que se
	está abocado a usar herencia múltiple si se quiere usar esta
	aproximación. Se verá en el capítulo 16 que las plantillas
	solucionan este problema de una forma más simple y elegante.
      </para>
    </sect2>
  </sect1>

  <sect1>
    <title>Sobrecarga de operadores</title>

    <para>
      Se pueden crear operadores <kw>virtual</kw>es de forma
      análoga a otras funciones miembro. Sin embargo implementar
      operadores <kw>virtual</kw>es se vuelve a menudo confuso
      porque se está operando sobre dos objetos, ambos sin tipos
      conocidos. Esto suele ser el caso de los componentes matemáticos
      (para los cuales se suele usar la sobrecarga de operadores). Por
      ejemplo, considere un sistema que usa matrices, vectores y valores
      escalares, todos ellos heredados de la clase
      <classname>Math</classname>:
    </para>


//: V1C15:OperatorPolymorphism.cpp


    <para>
      Para simplificar sólo se ha sobrecargado el
      <type>operator*</type>. El objetivo es ser capaz de
      multiplicar dos objetos <classname>Math</classname> cualquiera y
      producir el resultado deseado - hay que darse cuenta que
      multiplicar una matriz por un vector es una operación totalmente
      distinta a la de multiplicar un vector por una matriz.
    </para>

    <para>
      El problema es que, en el <function>main()</function>, la
      expresión <literal>m1 * m2</literal> contiene dos referencias
      <classname>Math</classname>, y son dos objetos de tipo
      desconocido. Una función virtual es sólo capaz de hacer una única
      llamada - es decir, determinar el tipo de un único objeto. Para
      determinar ambos tipos en este ejemplo se usa una técnica conocida
      como despachado múltiple (<foreignphrase>multiple
      dispatching</foreignphrase>), donde lo que parece ser una única
      llamada a una función virtual se convierte en una segunda llamada
      a una función virtual. Cuando la segunda llamada se ha ejecutado,
      ya se han determinado ambos tipos de objetos y se puede ejecutar
      la actividad de forma correcta. En un principio no es
      transparante, pero después de un rato mirando el código empieza a
      cobrar sentido. Esta materia es tratada con más profundidad en el
      capítulo de los patrones de diseño en el Volumen 2 que se puede
      bajar de <ulink
      url="http://www.bruceeckel.com">>www.BruceEckel.com</ulink>.
    </para>
  </sect1>

  <sect1>
    <title>Downcasting</title>

    <para>
      Como se puede adivinar, desde el momento que existe algo conocido
      como upcasting - mover en sentido ascendente por una jerarquía de
      herencia - debe existir el
      <foreignphrase>downcasting</foreignphrase> para mover en sentido
      descendente en una jerarquía. Pero el upcasting es sencillo porque
      al movernos en sentido ascendente en la jerarquía de clases
      siempre convergemos en clases más generales. Es decir, cuando se
      hace un upcast siempre se está en una clase claramente derivada de
      un ascendente (normalmente solo uno, excepto en el caso de
      herencia múltiple) pero cuando se hace downcast hay normalmente
      varias posibilidades a las que amoldarse. Mas concretamente, un
      <classname>Circulo</classname> es un tipo de
      <classname>Figura</classname> (que sería su
      <foreignphrase>upcast</foreignphrase>), pero si se intenta hacer
      un <foreignphrase>downcast</foreignphrase> de una
      <classname>Figura</classname> podría ser un
      <classname>Circulo</classname>, un
      <classname>Cuadrado</classname>, un
      <classname>Triángulo</classname>, etc. El problema es encontrar un
      modo seguro de hacer <foreignphrase>downcast</foreignphrase>
      (aunque es incluso más importante preguntarse por qué se está
      usando <foreignphrase>downcasting</foreignphrase> en vez de usar
      el polimorfismo para que adivine automáticamente el tipo
      correcto. En el Volumen 2 de este libro se trata como evitar el
      <foreignphrase>downcasting</foreignphrase>.
    </para>

    <para>
      C++ proporciona un moldeado explícito especial (introducido en el
      capítulo 3) llamado "moldeado dinámico"
      (<foreignphrase>dynamic_cast</foreignphrase>) que es una operación
      segura. Cuando se usa <emphasis>moldeado dinámico</emphasis> para
      intentar hacer un molde a un tipo en concreto, el valor de retorno
      será un puntero al tipo deseado sólo si el molde es adecuado y
      tiene éxito, de otra forma devuelve cero para indicar que no es
      del tipo correcto. Aquí tenemos un ejemplo mínimo:
    </para>


//: V1C15:DynamicCast.cpp


    <para>
      Cuando se use <emphasis>moldeado dinámico</emphasis>, hay que
      trabajar con una jerarquía polimórfica real - con funciones
      virtuales - debido a que el <emphasis>modeado dinámico</emphasis>
      usa información almacenada en la VTABLE para determinar el tipo
      actual. Aquí, la clase base contiene un destructor virtual y esto
      es suficiente. En el <function>main()</function>, un puntero a
      <classname>Cat</classname> es elevado a
      <classname>Pet</classname>, y después se hace un downcast tanto a
      puntero <classname>Dog</classname> como a puntero a
      <classname>Cat</classname>. Ambos punteros son imprimidos, y se
      puede observar que cuando se ejecuta el programa el
      <foreignphrase>downcast</foreignphrase> incorrecto produce el
      valor cero. Por supuesto somos los responsables de comprobar que
      el resultado del cast no es cero cada vez que se haga un
      downcast. Además no hay que asumir que el puntero será exactamente
      el mismo, porque a veces se realizan ajustes de punteros durante
      el <foreignphrase>upcasting</foreignphrase> y el
      <foreignphrase>downcasting</foreignphrase> (en particular, con la
      herencia múltiple).
    </para>

    <para>
      Un <emphasis>moldeado dinámico</emphasis> requiere un poco de
      sobrecarga extra en ejecución; no mucha, pero si se está haciendo
      mucho <emphasis>moldeado dinámico</emphasis> (en cuyo caso debería
      ser cuestionado seriamente el diseño del programa) se convierte en
      un lastre en el rendimiento. En algunos casos se puede tener
      alguna información especial durante el downcasting que permita
      conocer el tipo que se está manejando, con lo que la sobrecarga
      extra del <emphasis>modeado dinámico</emphasis> se vuelve
      innecesario, y se puede usar de manera alternativa un
      <emphasis>moldeado estático</emphasis>. Aquí se muestra como
      funciona:
    </para>


//: V1C15:StaticHierarchyNavigation.cpp


    <para>
      En este programa, se usa una nueva característica que no será
      completamente descrita hasta el Volumen 2 de este libro, donde hay
      un capítulo que cubre este tema: <emphasis>Información de tipo en
      tiempo de ejecución en C++</emphasis> o mecanismo RTTI
      (<foreignphrase>run time type information</foreignphrase>). RTTI
      permite descubrir información de tipo que ha sido perdida en el
      upcasting. El <emphasis>moldeado dinámico</emphasis> es
      actualmente una forma de RTTI. Aquí se usa la palabra reservada
      <kw>typeid</kw> (declarada en el fichero cabecera
      <filename>typeinfo</filename>) para detectar el tipo de los
      punteros. Se puede ver que el tipo del puntero a
      <classname>Figura</classname> es comparado de forma sucesiva con
      un puntero a <classname>Circulo</classname> y con un
      <classname>Cuadrado</classname> para ver si existe alguna
      coincidencia. Hay más RTTI que el <kw>typeid</kw>, y se
      puede imaginar que es fácilmente implementable un sistema de
      información de tipos usando una función virtual.
    </para>

    <para>
      Se crea un objeto <classname>Circulo</classname> y la dirección es
      elevada a un puntero a <classname>Figura</classname>; la segunda
      versión de la expresión muestra como se puede usar
      <emphasis>modeado estático</emphasis> para ser más explícito con el
      upcast. Sin embargo, desde el momento que un upcast siempre es
      seguro y es una cosa que se hace comunmente, considero que un cast
      explícito para hacer upcast ensucia el código y es innecesario.
    </para>

    <para>
      Para determinar el tipo se usa RTTI, y se usa <emphasis>modelado
	estático</emphasis> para realizar el downcast. Pero hay que
	resaltar que, efectivamente, en este diseño el proceso es el
	mismo que usar el <emphasis>moldeado dinámico</emphasis>, y el
	programador cliente debe hacer algún test para descubrir si el
	cast tuvo éxito. Normalmente se prefiere una situación más
	determinista que la del ejemplo anterior para usar el
	<emphasis>modeado estático</emphasis> antes que el
	<emphasis>moldeado dinámico</emphasis> (y hay que examinar
	detenidamente el diseño antes de usar
	<emphasis>moldeado dinámico</emphasis>).
    </para>

    <para>
      Si una jerarquía de clases no tiene funciones
      <kw>virtual</kw>es (que es un diseño cuestionable) o si
      hay otra información que permite hacer un downcast seguro, es un
      poco más rápido hacer el downcast de forma estática que con el
      <emphasis>moldeado dinámico</emphasis>. Además, <emphasis>modeado
      estático</emphasis> no permitirá realizar un cast fuera de la
      jerarquía, como un cast tradicional permitiría, por lo que es más
      seguro. Sin enbargo, navegar de forma estática por la jerarquía de
      clases es siempre arriesgado por lo que hay que usar
      <emphasis>moldeado dinámico</emphasis> a menos que sea una
      situación especial.
    </para>
  </sect1>

  <sect1>
    <title>Resumen</title>

    <para>
      Polimorfismo - implementado en C++ con las funciones virtuales -
      significa "formas diferentes". En la programación orientada a
      objetos, se tiene la misma vista (la interfaz común en la clase
      base) y diferentes formas de usarla: las diferentes versiones de
      las funciones virtuales.
    </para>

    <para>
      Se ha visto en este capítulo que es imposible entender, ni
      siquiera crear, un ejemplo de polimorfismo sin usar la abstracción
      de datos y la herencia. El polimorfismo es una característica que
      no puede ser vista de forma aislada (como por ejemplo las
      sentencias <kw>const</kw> y <kw>switch</kw>),
      pero sin embargo funciona únicamente de forma conjunta, como una
      parte de un "gran cuadro" de relaciones entre clases. La gente se
      vuelve a menudo confusa con otras características no orientadas a
      objetos de C++ como es la sobrecarga y los argumentos por defecto,
      los cuales son presentados a veces como orientado a objetos. No
      nos liemos; si no hay ligadura dinámica, no hay polimorfismo.
    </para>

    <para>
      Para usar el polimorfismo - y por lo tanto, técnicas orientadas a
      objetos - en los programas hay que ampliar la visión de la
      programación para incluir no solo miembros y mensajes entre clases
      individuales, si no también sus puntos en común y las relaciones
      entre ellas. Aunque requiere un esfuerzo significativo, es
      recompensado gracias a que se consigue mayor velocidad en el
      desarrollo, mejor organización de código, programas extensibles, y
      mayor mantenibilidad.
    </para>

    <para>
      El polimorfismo completa las características de orientación a
      objetos del lenguaje, pero hay dos características fundamentales
      más en C++: plantillas (introducidas en el capítulo 16 y cubiertas
      en mayor detalle en el segundo volumen de este libro), y manejo de
      excepciones (cubierto en el Volumen 2). Estas características nos
      proporcionan un incremento de poder de cada una de las
      características de la orientación a objetos: tipado abstracto de
      datos, herencia, y polimorfismo.
    </para>
  </sect1>

  <sect1>
    <title>Ejercicios</title>

    <xi:include parse="xml" href="./ejercicios.xml"/>

    <orderedlist>
      <listitem>
	<para>
	  Cree una jerarquía simple "figura": una clase base llamada
	  <classname>Figura</classname> y una clases derivadas llamadas
	  <classname>Circulo</classname>,
	  <classname>Cuadrado</classname>, y
	  <classname>Triangulo</classname>. En la clase base, hay que
	  hacer una función virtual llamada
	  <function>dibujar()</function>, y sobreescribirla en las
	  clases derivadas. Hacer un array de punteros a objetos
	  <classname>Figura</classname> que se creen en el montón (heap)
	  y que obligue a realizar upcasting de los punteros, y llamar a
	  <function>dibujar()</function> a través de la clase base para
	  verificar el comportamiento de las funciones virtuales. Si el
	  depurador lo soporta, intente ver el programa paso a paso.
	</para>
      </listitem>
      <listitem>
	<para>
	  Modifique el Ejercicio 1 de tal forma que
	  <function>dibujar()</function> sea una función virtual
	  pura. Intente crear un objeto de tipo
	  <classname>Figura</classname>. Intente llamar a la función
	  virtual pura dentro del constructor y mire lo que
	  ocurre. Dejándolo como una función virtual pura cree una
	  definición para <function>dibujar()</function>.
	</para>
      </listitem>
      <listitem>
	<para>
	  Aumentando el Ejercicio 2, cree una función que use un objeto
	  <classname>Figura</classname> <emphasis>por valor</emphasis> e
	  intente hacer un upcast de un objeto derivado como
	  argumento. Vea lo que ocurre. Arregle la función usando una
	  referencia a un objeto <classname>Figura</classname>.
	</para>
      </listitem>
      <listitem>
	<para>
	  Modifique <filename>C14:Combined.cpp</filename> para que
	  <function>f()</function> sea <kw>virtual</kw> en la
	  clase base. Cambie el <function>main()</function> para que se
	  haga un <foreignphrase>upcast</foreignphrase> y una llamada virtual.
	</para>
      </listitem>
      <listitem>
	<para>
	  Modifique <filename>Instrument3.cpp</filename> añadiendo una
	  función virtual <function>preparar()</function>. Llame a
	  <function>preparar()</function> dentro de
	  <function>tune()</function>.
	</para>
      </listitem>
      <listitem>
	<para>
	  Cree una jerarquía de herencia de
	  <classname>Roedor</classname>es: <classname>Raton</classname>,
	  <classname>Gerbo</classname>, <classname>Hamster</classname>,
	  etc. En la clase base, proporcione los métodos que son comunes
	  a todos los roedores, y redefina aquellos en las clases
	  derivadas para que tengan diferentes comportamientos
	  dependiendo del tipo específico de roedor. Cree un array de
	  punteros a <classname>Roedor</classname>, rellenelo con distintos
	  tipos de roedores y llame a los métodos de la clase base para
	  ver lo que ocurre.
	</para>
      </listitem>
      <listitem>
	<para>
	  Modifique el Ejercicio 6 para que use un
	  <literal>vector&lt;Roedor*&gt; </literal> en vez de un array
	  de punteros. Asegurese que se hace un limpiado correcto de la
	  memoria.
	</para>
      </listitem>
      <listitem>
	<para>
	  Empezando con la jerarquía anterior de
	  <classname>Roedor</classname>, herede un
	  <classname>HamsterAzul</classname> de
	  <classname>Hamster</classname> (si, existe algo así, tuve uno
	  cuando era niño), sobreescriba los métodos de la clase base y
	  muestre que el código que llama a los métodos de clase base no
	  necesitan cambiar para adecuarse el nuevo tipo.
	</para>
      </listitem>
      <listitem>
	<para>
	  A partir de la jerarquía <classname>Roedor</classname> anterior,
	  añadaun destructor no virtual, cree un objeto de la
	  <classname>Hamster</classname> usando <kw>new</kw>,
	  haga un upcast del puntero a <type>Roedor*</type>, y
	  borre el puntero con <kw>delete</kw> para ver si no
	  se llama a los destructores en la jerarquía. Cambie el
	  destructor a <kw>virtual</kw> y demuestre que el
	  comportamiento es ahora correcto.
	</para>
      </listitem>
      <listitem>
	<para>
	  Modifique <classname>Roedor</classname> para convertirlo en una
	  clase base pura abstracta.
	</para>
      </listitem>
      <listitem>
	<para>
	  Cree un sistema de control aéreo con la clase base
	  <classname>Avion</classname> y varios tipos derivados. Cree
	  una clase <classname>Torre</classname> con un
	  <literal>vector&lt;Avion*&gt; </literal> que envie los
	  mensajes adecuados a los distintos aviones que están bajo su
	  control.
	</para>
      </listitem>
      <listitem>
	<para>
	  Cree un modelo de invernadero heredando varios tipos de
	  <classname>Planta</classname>s y construyendo mecanismos en el
	  invernadero que se ocupen de las plantas.
	</para>
      </listitem>
      <listitem>
	<para>
	  En <filename>Early.cpp</filename>, haga a
	  <classname>Pet</classname> una clase base abstracta pura.
	</para>
      </listitem>
      <listitem>
	<para>
	  En <filename>AddingVirtuals.cpp</filename>, haga a todas las
	  funciones miembro de <classname>Pet</classname> virtuales
	  puras, pero proporcione una definición para
	  <function>name()</function>. Arregle <classname>Dog</classname>
	  como sea necesario, usando la definición de
	  <function>name()</function> que se encuentra en la clase base.
	</para>
      </listitem>
      <listitem>
	<para>
	  Escriba un pequeño programa para mostrar la diferencia entre
	  llamar a una función virtual dentro de una función miembro
	  normal y llamar a una función virtual dentro de un
	  constructor. El programa de probar que las dos llamadas
	  producen diferentes resultados.
	</para>
      </listitem>
      <listitem>
	<para>
	  Modifique <filename>VirtualsInDestructors.cpp</filename> por
	  heredando una clase de <classname>Derived</classname> y
	  sobreescribiendo <function>f()</function> y el destructor. En
	  <function>main()</function>, cree y haga un upcast de un objeto
	  de su nuevo tipo, después borrelo.
	</para>
      </listitem>
      <listitem>
	<para>
	  Use el Ejercicio 16 y añada llamadas a <function>f()</function>
	  en cada destructor. Explique que ocurre.
	</para>
      </listitem>
      <listitem>
	<para>
	  Cree un clase que tenga un dato miembro y una clase derivada
	  que añada otro dato miembro. Escriba una función no miembro
	  que use un objeto de la clase base <emphasis>por
	  valor</emphasis> e imprima el tamaño del objeto usando
	  <oper>sizeof</oper>. En el <function>main()</function>
	  cree un objeto de la clase derivada, imprima su tamaño, y
	  llame a su función. Explique lo que ocurre.
	</para>
      </listitem>
      <listitem>
	<para>
	  Cree un ejemplo sencillo de una llamada a una función virtual
	  y genere su salida en ensamblador. Localize el código en
	  ensamblador para la llamada a la función virtual y explique el
	  código.
	</para>
      </listitem>
      <listitem>
	<para>
	  Escriba una clase con una función virtual y una función no
	  virtual. Herede una nueva clase, haga un objeto de esa clase,
	  y un upcast a un puntero del tipo de la clase base. Use la
	  función <function>clock()</function> que se encuentra en
	  <filename>&lt;ctime&gt;</filename> (necesitará echar un vistazo
	  a su librerí C) para medir la diferencia entre una llamada
	  virtual y una llamada no virtual. Será necesario realizar
	  multiples llamadas a cada función para poder ver la
	  diferencia.
	</para>
      </listitem>
      <listitem>
	<para>
	  Modifique <filename>C14:Order.cpp </filename> añadiendo una
	  función virtual en la clase base de la macro
	  <literal>CLASS</literal> (que pinte algo) y haciendo el
	  destructor virtual. Cree objetos de las distintas subclases y
	  hagales un upcast a la clase base. Verifique que el
	  comportamiento virtual funciona y que se realiza de forma
	  correcta la construcción y la destrucción del objeto.
	</para>
      </listitem>
      <listitem>
	<para>
	  Escriba una clase con tres funciones virtuales
	  sobrecargadas. Herede una nueva clase y sobreescriba una de
	  las funciones. Cree un objeto de la clase derivada. ¿Se puede
	  llamar a todas las funciones de la clase base a través del
	  objeto derivado? Haga un <foreignphrase>upcast</foreignphrase>
	  de la dirección del objeto a la base. ¿Se pueden llamar a las
	  tres funciones a través de la base? Elimine la definición
	  sobreescrita en la clase derivada. Ahora ¿Se puede llamar a
	  todas las funciones de la clase base a través del objeto
	  derivado?.
	</para>
      </listitem>
      <listitem>
	<para>
	  Modifique <filename>VariantReturn.cpp</filename> para que
	  muestre que su comportamiento funciona con referencias igual
	  que con punteros.
	</para>
      </listitem>
      <listitem>
	<para>
	  En <filename>Early.cpp</filename>, ¿Cómo se le puede indicar
	  al compilador que haga la llamada usando ligadura estática o
	  ligadura dinámica? Determine el caso para su propio
	  compilador.
	</para>
      </listitem>
      <listitem>
	<para>
	  Cree una clase base que contenga una función
	  <function>clone()</function> que devuelva un puntero a una
	  <emphasis>copia</emphasis> del objeto actual. Derive dos
	  subclases que sobreescriban <function>clone()</function> para
	  devolver copias de sus tipos específicos. En el
	  <function>main()</function>, cree y haga
	  <foreignphrase>upcast</foreignphrase> de sus dos tipos
	  derivados, y llame a <function>clone()</function> para cada
	  uno y verifique que las copias clonadas son de los subtipos
	  correctos. Experimente con su función
	  <function>clone()</function> para que se pueda ir al tipo
	  base, y después intente regresar al tipo exacto derivado. ¿Se
	  le ocurre alguna situación en la que sea necesario esta
	  aproximación?
	</para>
      </listitem>
      <listitem>
	<para>
	  Modifique <filename>OStackTest.cpp</filename> creando su
	  propia clase, después haga multiple herencia con
	  <classname>Object</classname> para crear algo que pueda ser
	  introducido en la pila. Pruebe su clase en el
	  <function>main()</function>.
	</para>
      </listitem>
      <listitem>
	<para>
	  Añada un tipo llamado <classname>Tensor</classname> a
	  <filename>OperartorPolymorphism.cpp</filename>.
	</para>
      </listitem>
      <listitem>
	<para>
	  (Intermedio) Cree una clase base <classname>X</classname> sin
	  datos miembro y sin constructor, pero con una función
	  virtual. Cree una <classname>Y</classname> que herede de
	  <classname>X</classname>, pero sin un constructor
	  explícito. Genere código ensamblador y examinelo para
	  deteriminar si se crea y se llama un constructor de
	  <classname>X</classname> y, si eso ocurre, qué código lo
	  hace. Explique lo que haya
	  descubierto. <classname>X</classname> no tiene constructor por
	  defecto, entonces ¿por qué no se queja el compilador?
	</para>
      </listitem>
      <listitem>
	<para>
	  (Intermedio) Modifique el Ejercicio 28 escribiendo
	  constructores para ambas clases de tal forma que cada
	  constructor llame a una función virtual. Genere el código
	  ensamblador. Determine donde se encuentra asignado el VPTR
	  dentro del constructor. ¿El compilador está usando el
	  mecanismo virtual dentro del constructor? Explique por qué se
	  sigue usando la version local de la función.
	</para>
      </listitem>
      <listitem>
	<para>
	  (Avanzado) Si una función llama a un objeto pasado por valor
	  si ligadura estática, una llamada virtual accede a partes que
	  no existen. ¿Es posible? Escriba un código para forzar una
	  llamada virtual y vea si se produce un cuelgue de la
	  aplicación. Para explicar el comportamiento, observe que
	  ocurre si se pasa un objeto por valor.
	</para>
      </listitem>
      <listitem>
	<para>
	  (Avanzado) Encuentre exactamente cuanto tiempo más es
	  necesario para una llamada a una función virtual buscando en
	  la información del lenguaje ensamblador de su procesador o
	  cualquier otro manual técnico y encontrando los pulsos de
	  reloj necesarios para una simple llamada frente al número
	  necesario de las instrucciones de las funciones virtuales.
	</para>
      </listitem>
      <listitem>
	<para>
	  Determine el tamaño del VPTR (usando
	  <oper>sizeof</oper>) en su implementación. Ahora herede
	  de dos clases (herencia múltiple) que contengan funciones
	  virtuales. ¿Se tiene una o dos VPTR en la clase derivada?
	</para>
      </listitem>
      <listitem>
	<para>
	  Cree una clase con datos miembros y funciones
	  virtuales. Escriba una función que mire en la memoria de un
	  objeto de su clase y que imprima sus distintos
	  fragmentos. Para hacer esto será necesario experimentar y de
	  forma iterativa descubrir donde se encuentra alojado el VPTR
	  del objeto.
	</para>
      </listitem>
      <listitem>
	<para>
	  Imagine que las funciones virtuales no existen, y modifique
	  <filename>Instrument4.cpp</filename> para que use
	  <emphasis>moldeado dinámico</emphasis> para hacer el
	  equivalente de las llamadas virtuales. Esplique porque es una
	  mala idea.
	</para>
      </listitem>
      <listitem>
	<para>
	  Modifique <filename>StaicHierarchyNavigation.cpp</filename>
	  para que en vez de usar el RTTI de C++ use su propio RTTI via
	  una función virtual en la clase base llamada
	  <function>whatAmI()</function> y un <literal>enum type {
	  Circulos, Cuadrados };</literal>.
	</para>
      </listitem>
      <listitem>
	<para>
	  Comience con <filename>PointerToMemberOperator.cpp </filename>
	  del capítulo 12 y demuestre que el polimorfismo todavía
	  funciona con punteros a miembros, incluso si
	  <literal>operator-&gt;*</literal> está sobrecargado.
	</para>
      </listitem>
    </orderedlist>
  </sect1>
</chapter>