1. CRySoL
  2. Untitled project
  3. PensarEnC++

Source

PensarEnC++ / V1-C04.xml

The branch 'PensarEnC++' does not exist.
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
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
<?xml  version="1.0" encoding="utf-8"?>
<!-- -*- sgml -*- -->
<!--
  Editor:              Emacs 22/PSGML
  Traducción original: Sebastián Gurin <sgurin@motevideo.com.uy>
                       David Villa <dvilla@gmx.net>
  Formateado DocBook:  Sebastián Gurin <sgurin@motevideo.com.uy>
                       David Villa <dvilla@gmx.net>
  1ª Revisión:         David Villa
  2ª Revisión
-->


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

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

  <title>Abstracción de Datos</title>

  <!--
  C++ is a productivity enhancement tool. Why else would you make
  the effort (and it is an effort, regardless of how easy we attempt to
  make the transition)
  -->
  <highlights>
    <para>
      C++ es una herramienta de mejora de la productividad. ¿Por qué
      si no haría el esfuerzo (y es un esfuerzo, a pesar de lo fácil que
      intetemos hacer la transición)
    </para>
  </highlights>

  <!--
  to switch from some language that you already know and are
  productive with to a new language in which you're going to be less
  productive for a while, until you get the hang of it? It's because
  you've become convinced that you're going to get big gains by
  using this new tool.
  -->
  <para>
    de cambiar de algún lenguaje que ya conoce y con el cual ya es
    productivo a un nuevo lenguaje con el que será menos productivo
    durante un tiempo, hasta que se haga con él? Se debe a que está
    convencido de que conseguirá grandes ventajas usando esta nueva
    herramienta.
  </para>


  <!--
  Productivity, in computer programming terms, means that fewer people
  can make much more complex and impressive programs in less time. There
  are certainly other issues when it comes to choosing a language, such
  as efficiency (does the nature of the language cause slowdown and code
  bloat?), safety (does the language help you ensure that your program
  will always do what you plan, and handle errors gracefully?), and
  maintenance (does the language help you create code that is easy to
  understand, modify, and extend?). These are certainly important
  factors that will be examined in this book.
  -->
  <para>
    En términos de programación, productividad significa que menos
    personas, en menos tiempo, puedan realizar programas más complejos y
    significativos. Desde luego, hay otras cuestiones que nos deben
    importar a la hora de escoger un lenguaje de programación. Aspectos
    a tener en cuenta son la eficiencia (¿la naturaleza del lenguaje
    hace que nuestros programas sean lentos o demasiado grandes?), la
    seguridad (¿nos ayuda el lenguaje a asegurarnos de que nuestros
    programas hagan siempre lo que queremos?  ¿maneja el lenguaje los
    errores apropiadamente?)  y el mantenimiento (¿el lenguaje ayuda a
    crear código fácil de entender, modificar y extender?). Estos son,
    con certeza, factores importantes que se examinarán en este libro.
  </para>

  <!--
  But raw productivity means a program that formerly took three of you a
  week to write now takes one of you a day or two. This touches several
  levels of economics. You're happy because you get the rush of power
  that comes from building something, your client (or boss) is happy
  because products are produced faster and with fewer people, and the
  customers are happy because they get products more cheaply. The only way
  to get massive increases in productivity is to leverage off other
  people's code. That is, to use libraries.
  -->
  <para>
    Pero la productividad real significa que un programa que para ser escrito, antes
    requería de tres personas trabajando una semana, ahora le lleve sólo un día o dos a
    una sola persona. Esto afecta a varios niveles de la esfera económica. A usted le
    agrada ver que es capaz de construir algo en menos tiempo, sus clientes (o jefe) están
    contentos porque los productos les llegan más rápido y utilizando menos mano
    de obra y finalmente los compradores se alegran porque pueden obtener productos más
    baratos. La única manera de obtener incrementos masivos en productividad es apoyándose
    en el código de otras personas; o sea, usando librerías.
  </para>

  <!--
  A library is simply a bunch of code that someone else has written and
  packaged together. Often, the most minimal package is a file with an
  extension like lib and one or more header files to tell your compiler
  what's in the library. The linker knows how to search through the
  library file and extract the appropriate compiled code. But that's only
  one way to deliver a library. On platforms that span many architectures,
  such as Linux/Unix, often the only sensible way to deliver a library is
  with source code, so it can be reconfigured and recompiled on the new
  target.
  -->
  <para>
    Una librería es simplemente un montón de código que alguien ha
    escrito y empaquetado todo junto. Muchas veces, el paquete mínimo es
    tan sólo un archivo con una extensión especial como
    <filename>lib</filename> y uno o más archivos de cabecera que le
    dicen al compilador qué contiene la librería. El enlazador sabrá cómo
    buscar el archivo de la librería y extraer el código compilado
    correcto. Sin embargo, ésta es sólo una forma de entregar una
    librería. En plataformas que abarcan muchas arquitecturas, como
    GNU o Unix, el único modo sensato de entregar una libraría es con
    código fuente para que así pueda ser reconfigurado y reconstruido en
    el nuevo objetivo.
  </para>


  <!--
  Thus, libraries are probably the most important way to improve
  productivity, and one of the primary design goals of C++ is to make
  library use easier. This implies that there's something hard about
  using libraries in C. Understanding this factor will give you a first
  insight into the design of C++, and thus insight into how to use it.
  -->
  <para>
    De esta forma, las librerías probablemente sean la forma más
    importante de progresar en términos de productividad y uno de los
    principales objetivos del diseño de C++ es hacer más fácil el uso de
    librerías. Esto implica entonces, que hay algo difícil al usar
    librerías en C. Entender este factor le dará una primera idea sobre
    el diseño de C++, y por lo tanto, de cómo usarlo.
  </para>


  <sect1>
    <!--   A tiny C-like library -->
    <title>Una librería pequeña al estilo C</title>

    <!--
    A library usually starts out as a collection of functions, but if
    you have used third-party C libraries you know there's usually more
    to it than that because there's more to life than behavior,
    actions, and functions. There are also characteristics (blue,
    pounds, texture, luminance), which are represented by data. And when
    you start to deal with a set of characteristics in C, it is very
    convenient to clump them together into a struct, especially if you
    want to represent more than one similar thing in your problem
    space. Then you can make a variable of this struct for each thing.
    -->
    <para>
      Aunque muchas veces, una librería comienza como una colección de
      funciones, si ha usado alguna librería C de terceros habrá
      observado que la cosa no termina ahí porque hay más que
      comportamiento, acciones y funciones. También hay características
      (azul, libras, textura, luminiscencia), las cuales están
      representadas por datos. En C, cuando debemos representar
      características, es muy conveniente agruparlas todas juntas en una
      <emphasis>estructura</emphasis>, especialmente cuando queremos
      representar más de un tipo de cosa en el problema. Así, se puede
      trabajar con una variable de esta
      <emphasis>estructuras</emphasis> para representar cada cosa.
    </para>




    <!--
    Thus, most C libraries have a set of structs and a set of
    functions that act on those structs. As an example of what such a
    system looks like, consider a programming tool that acts like an
    array, but whose size can be established at runtime, when it is
    created. I'll call it a CStash. Although it's written in C++, it
    has the style of what you'd write in C:
    -->
    <para>
      Por eso, la mayoría de las librerías en C están formadas por un
      conjunto de estructuras y funciones que actúan sobre las
      primeras. Como ejemplo de esta técnica, considere una herramienta
      de programación que se comporta como un array, pero cuyo tamaño se
      puede fijar en tiempo de ejecución, en el momento de su
      creación. La llamaremos <type>CStash</type>
      <footnote>
        <para>
          N de T:<quote>Stash</quote> se podría traducir como
          <quote>Acumulador</quote>.
        </para>
      </footnote>. Aunque está escrito en C++, tiene el estilo clásico
      de una librería escrita en C:
    </para>


//: V1C04:CLib.h



  <!--
  A tag name like CStashTag is generally used for a struct in case you
  need to reference the struct inside itself. For example, when creating a
  linked list (each element in your list contains a pointer to the next
  element), you need a pointer to the next struct variable, so you need a
  way to identify the type of that pointer within the struct body. Also,
  you'll almost universally see the typedef as shown above for every
  struct in a C library. This is done so you can treat the struct as if it
  were a new type and define variables of that struct like this:
  -->

    <para>
      Normalmente se utiliza un <quote>rótulo</quote> como
      <type>CStashTag</type> en aquellas estructuras que necesitan
      referenciarse dentro de si mismas. Ese es el caso de una
      <emphasis>lista enlazada</emphasis> (cada elemento de la lista
      contiene un puntero al siguiente elemento) se necesita un puntero a
      la siguiente variable estructura, o sea, una manera de identificar
      el tipo de ese puntero dentro del cuerpo de la propia
      estructura. En la declaración de las estructuras de una librería
      escrita en C también es muy común ver el uso de <kw>typedef</kw>
      como el del ejemplo anterior. Esto permite al programador tratar
      las estructuras como un nuevo tipo de dato y así definir nuevas
      variables (de esa estructura) del siguiente modo:
    </para>


<programlisting>
CStash A, B, C;
</programlisting>


    <!--
    The storage pointer is an unsigned char*. An unsigned char is
    the smallest piece of storage a C compiler supports, although on
    some machines it can be the same size as the largest. It's
    implementation dependent, but is often one byte long. You might
    think that because the CStash is designed to hold any type of
    variable, a void* would be more appropriate here. However, the
    purpose is not to treat this storage as a block of some unknown
    type, but rather as a block of contiguous bytes.  -->
    <para>
      El puntero <varname>storage</varname> es un <type>unsigned
      char*</type>. Un <type>unsigned char</type> es la menor pieza de
      datos que permite un compilador C, aunque en algunas máquinas
      puede ser de igual tamaño que la mayor. Aunque es dependiente de
      la implementación, por lo general un <type>unsigned char</type>
      tiene un tamaño de un byte. Dado que <type>CStash</type> está
      diseñado para almacenar cualquier tipo de estructura, el lector se
      puede preguntar si no sería más apropiado un puntero <type>void
      *</type>. Sin embargo, el objetivo no es tratar este puntero de
      almacenamiento como un bloque de datos de tipo desconocido, sino
      como un bloque de bytes contiguos.
    </para>

    <!--
    The source code for the implementation file (which you may not
    get if you buy a library commercially ? you might get only a
    compiled obj or lib or dll, etc.) looks like this: -->
    <para>
      El archivo de código fuente para la implementación (del que no se
      suele disponer si fuese una librería comercial &mdash;normalmente sólo
      dispondrá de un <filename>.obj</filename>,
      <filename>.lib</filename> o <filename>.dll</filename>, etc) tiene
      este aspecto:
    </para>


//: V1C04:CLib.cpp


    <!--
    initialize( ) performs the necessary setup for struct CStash by setting
    the internal variables to appropriate values. Initially, the storage
    pointer is set to zero ? no initial storage is allocated.
    -->

    <para>
      <function>initialize()</function> realiza las operaciones
      iniciales necesarias para la <type>struct CStash</type>, poniendo
      los valores apropiados en las variables internas. Inicialmente, el
      puntero <varname>storage</varname> tiene un cero dado que aún no
      se ha almacenado nada.
    </para>

    <!--
    The add( ) function inserts an element into the CStash at the next
    available location. First, it checks to see if there is any available
    space left. If not, it expands the storage using the inflate( )
    function, described later.
    -->

    <para>
      La función <function>add()</function> inserta un elemento en el
      siguiente lugar disponible de la <type>CStash</type>. Para
      lograrlo, primero verifica que haya suficiente espacio
      disponible. Si no lo hay, expande el espacio de almacenamiento
      (<varname>storage</varname>) usando la función
      <function>inflate()</function> que se describe después.
    </para>

    <!--
    Because the comqpiler doesn?t know the specific type of the
    variable being stored (all the function gets is a void*), you can?t
    just do an assignment, which would certainly be the convenient
    thing. Instead, you must copy the variable byte-by-byte. The most
    straightforward way to perform the copying is with array
    indexing. Typically, there are already data bytes in storage, and
    this is indicated by the value of next. To start with the right byte
    offset, next is multiplied by the size of each element (in bytes) to
    produce startBytes. Then the argument element is cast to an unsigned
    char* so that it can be addressed byte-by-byte and copied into the
    available storage space. next is incremented so that it indicates
    the next available piece of storage, and the ?index number? where
    the value was stored so that value can be retrieved using this index
    number with fetch( ).
    -->

    <para>
      Como el compilador no conoce el tipo específico de la variable que
      está siendo almacenada (todo lo que obtiene la función es un
      <type>void*</type>), no se puede hacer una asignación simple, que
      sería lo más conveniente. En lugar de eso, la variable se copia
      byte a byte. La manera más directa de hacerlo es utilizando el
      indexado de arrays. Lo habitual es que en
      <varname>storage</varname> ya haya bytes almacenados, lo cual es
      indicado por el valor de <varname>next</varname>. Para obtener la
      posición de inserción correcta en el array, se multiplica
      <varname>next</varname> por el tamaño de cada elemento (en bytes)
      lo cual produce el valor de <varname>startBytes</varname>. Luego
      el argumento <varname>element</varname> se moldea a <type>unsigned
      char*</type> para que se pueda direccionar y copiar byte a byte en
      el espacio disponible de <varname>storage</varname>. Se incrementa
      <varname>next</varname> de modo que indique el siguiente lugar de
      almacenamiento disponible y el <quote>índice</quote> en el que ha
      almacenado el elemento para que el valor se puede recuperar
      utilizando el índice con <function>fetch()</function>.
    </para>


    <!--
    fetch( ) checks to see that the index isn?t out of bounds and then
    returns the address of the desired variable, calculated using the
    index argument. Since index indicates the number of elements to
    offset into the CStash, it must be multiplied by the number of bytes
    occupied by each piece to produce the numerical offset in
    bytes. When this offset is used to index into storage using array
    indexing, you don?t get the address, but instead the byte at the
    address. To produce the address, you must use the address-of
    operator &.
    -->

    <para>
      <function>fetch()</function> verifica que el índice tenga un valor
      correcto y devuelve la dirección de la variable deseada, que se
      calcula en función del argumento <varname>index</varname>. Dado
      que <varname>index</varname> es un desplazamiento desde el
      principio en la <type>CStash</type>, se debe multiplicar por el
      tamaño en bytes que ocupa cada elemento para obtener dicho
      desplazamiento en bytes. Cuando utilizamos este desplazamiento
      como índice del array <varname>storage</varname> lo que obtenemos
      no es la dirección, sino el byte almacenado. Lo que hacemos
      entonces es utilizar el operador dirección-de <oper>&amp;</oper>.
    </para>

    <!--count( ) may look a bit strange at first to a seasoned C
    programmer. It seems like a lot of trouble to go through to do
    something that would probably be a lot easier to do by hand. If you
    have a struct CStash called intStash, for example, it would seem
    much more straightforward to find out how many elements it has by
    saying intStash.next instead of making a function call (which has
    overhead), such as count(&intStash). However, if you wanted to
    change the internal representation of CStash and thus the way the
    count was calculated, the function call interface allows the
    necessary flexibility. But alas, most programmers won?t bother to
    find out about your ?better? design for the library. They?ll look at
    the struct and grab the next value directly, and possibly even
    change next without your permission. If only there were some way for
    the library designer to have better control over things like this!
    (Yes, that?s foreshadowing.)-->

    <para>
      <function>count()</function> puede parecer un poco extraña a los
      programadores experimentados en C. Podría parecer demasiado
      complicada para una tarea que probablemente sea mucho más fácil de
      hacer a mano. Por ejemplo, si tenemos una <type>CStash</type>
      llamada <varname>intStash</varname>, es mucho más directo
      preguntar por la cantidad de elementos utilizando
      <varname>intStash.next</varname>, que llamar a una función (que
      implica sobrecarga), como
      <function>count(&amp;intStash)</function>. Sin embargo, la
      cantidad de elementos se calcula en función tanto del puntero
      <varname>next</varname> como del tamaño en bytes de cada elemento
      de la <type>CStash</type>; por eso la interfaz de la función
      <function>count()</function> permite la flexibilidad necesaria
      para no tener que preocuparnos por estas cosas. Pero, ¡ay!, la
      mayoría de los programadores no se preocuparán por descubrir lo
      que para nosotros es el <quote>mejor</quote> diseño para la
      librería. Probablemente lo que harán es mirar dentro de la
      estructura y obtener el valor de <varname>next</varname>
      directamente. Peor aún, podrían incluso cambiar el valor de
      <varname>next</varname> sin nuestro permiso. ¡Si hubiera alguna
      forma que permitiera al diseñador de la librería tener un mejor
      control sobre este tipo de cosas! (Sí, esto es un presagio).
    </para>


    <sect2>
      <!-- Dynamic storage allocation -->
      <title>Asignación dinámica de memoria</title>


      <!-- You never know the maximum amount of storage you might need
      for a CStash, so the memory pointed to by storage is allocated
      from the heap. The heap is a big block of memory used for
      allocating smaller pieces at runtime. You use the heap when you
      don?t know the size of the memory you?ll need while you?re writing
      a program. That is, only at runtime will you find out that you
      need space to hold 200 Airplane variables instead of 20. In
      Standard C, dynamic-memory allocation functions include malloc( ),
      calloc( ), realloc( ), and free( ). Instead of library calls,
      however, C++ has a more sophisticated (albeit simpler to use)
      approach to dynamic memory that is integrated into the language
      via the keywords new and delete.  -->

      <para>
	Nunca se puede saber la cantidad máxima de almacenamiento que se
	necesitará para una <type>CStash</type>, por eso la memoria a la
	que apuntan los elementos de <varname>storage</varname> se
	asigna desde el <emphasis>montículo</emphasis>
	(<foreignphrase>heap</foreignphrase>)
	<footnote>
	  <para>N. de T.: <foreignphrase>heap</foreignphrase> se suele
	    traducir al castellano como <quote>montón</quote> o
	    <quote>montículo</quote>.
	  </para>
	</footnote>.

	El montículo es un gran bloque de memoria que se utiliza para
	asignar en pequeños trozos en tiempo de ejecución. Se usa el
	heap cuando no se conoce de antemano la cantidad de memoria que
	necesitará el programa que está escribiendo. Por ejemplo, eso
	ocurre en un programa en el que sólo en el momento de la
	ejecución se sabe si se necesia memoria para 200 variables
	<type>Avión</type> o para 20. En C Estándar, las funciones para
	asignación dinámica de memoria incluyen
	<function>malloc()</function>, <function>calloc()</function>,
	<function>realloc()</function> y <function>free()</function>. En
	lugar de llamadas a librerías, C++ cuenta con una técnica más
	sofisticada (y por lo tanto más fácil de usar) para tratar la
	memoria dinámica. Esta técnica está integrada en el lenguaje por
	medio de las palabras reservadas <kw>new</kw> y <kw>delete</kw>.
      </para>

      <!--The inflate( ) function uses new to get a bigger chunk of
      space for the CStash. In this situation, we will only expand
      memory and not shrink it, and the assert( ) will guarantee that a
      negative number is not passed to inflate( ) as the increase
      value. The new number of elements that can be held (after inflate(
      ) completes) is calculated as newQuantity, and this is multiplied
      by the number of bytes per element to produce newBytes, which will
      be the number of bytes in the allocation. So that we know how many
      bytes to copy over from the old location, oldBytes is calculated
      using the old quantity.-->

      <para>
	La función <function>inflate()</function> usa <kw>new</kw> para
	obtener más memoria para la <type>CStash</type>. En este caso el
	espacio de memoria sólo se amplia y nunca se
	reduce. <function>assert()</function> garantiza que no se pase
	un número negativo como argumento a
	<function>inflate()</function> como valor de incremento. La
	nueva cantidad de elmentos que se podrán almacenar (una vez se
	haya terminado <function>inflate()</function>) se determina en la
	variable <varname>newQuantity</varname> que se multiplica por
	el número de bytes que ocupa cada elemento, para obtener el
	nuevo número total de bytes de la asignación en la variable
	<varname>newBytes</varname>. Dado que se sabe cuántos bytes hay
	que copiar desde la ubicación anterior,
	<varname>oldBytes</varname> se calcula usando la cantidad
	antigua de bytes (<varname>quantity</varname>).
      </para>

      <!--
      The actual storage allocation occurs in the new-expression,
      which is the expression involving the new keyword: -->
      <para>
	La petición de memoria ocurre realmente en la
	<emphasis>expresión-new</emphasis> que involucra la palabra
	reservada <kw>new</kw>:
      </para>

<programlisting>
new unsigned char[newBytes];
</programlisting>

      <!-- The general form of the new-expression is: -->
      <para>
	La forma general de una <emphasis>expresión-new</emphasis>
	es:
      </para>

<programlisting>
new Tipo;
</programlisting>

      <!--
      in which Type describes the type of variable you want allocated on
      the heap. In this case, we want an array of unsigned char that is
      newBytes long, so that is what appears as the Type. You can also
      allocate something as simple as an int by saying:
      -->
      <para>
	donde <type>Tipo</type> describe el tipo de variable para la
	cual se solicita memoria en el
	<emphasis>montículo</emphasis>. Dado que en este caso, se desea
	asignar memoria para un array de <type>unsigned char</type> de
	<varname>newBytes</varname> elementos, eso es lo que aparece como
	<type>Tipo</type>. Del mismo modo, se puede asignar memoria para
	algo más simple como un <type>int</type> con la expresión:
      </para>

<programlisting>
new int;
</programlisting>

      <!--
      and although this is rarely done, you can see that the form is
      consistent.
      -->
      <para>
	y aunque esto se utiliza muy poco, demuestra que la sintaxis es
	consistente.
      </para>


      <!--
      A new-expression returns a pointer to an object of the exact
      type that you asked for. So if you say new Type, you get back a
      pointer to a Type. If you say new int, you get back a pointer to
      an int. If you want a new unsigned char array, you get back a
      pointer to the first element of that array. The compiler will
      ensure that you assign the return value of the new-expression to a
      pointer of the correct type.
      -->
      <para>
	Una <emphasis>expresión-new</emphasis> devuelve un
	<emphasis>puntero</emphasis> a un objeto del tipo exacto que se
	le pidió. De modo que con <code>new Tipo</code> se obtendrá un
	puntero a un objeto de tipo <type>Tipo</type>, y con <code>new
	int</code> obtendrá un puntero a un <type>int</type>. Si quiere
	un nuevo array de <type>unsigned char</type> la expresión
	devolverá un puntero al primer elemento de dicho array. El
	compilador verificará que se asigne lo que devuelve la
	<emphasis>expresión-new</emphasis> a una variable puntero del
	tipo adecuado.
      </para>

      <!-- Of course, any time you request memory it's possible for the
      request to fail, if there is no more memory. As you will learn,
      C++ has mechanisms that come into play if the memory-allocation
      operation is unsuccessful.  -->
      <para>
	Por supuesto, es posible que al pedir memoria, la petición
	falle, por ejemplo, si no hay más memoria libre en el
	sistema. Como verá más adelante, C++ cuenta con mecanismos que
	entran en juego cuando la operación de asignación de memoria no
	se puede satisfacer.
      </para>


      <!--
      Once the new storage is allocated, the data in the old storage
      must be copied to the new storage; this is again accomplished with
      array indexing, copying one byte at a time in a loop. After the
      data is copied, the old storage must be released so that it can be
      used by other parts of the program if they need new storage. The
      delete keyword is the complement of new, and must be applied to
      release any storage that is allocated with new (if you forget to
      use delete, that storage remains unavailable, and if this
      so-called memory leak happens enough, you'll run out of
      memory). In addition, there's a special syntax when you're
      deleting an array. It's as if you must remind the compiler that
      this pointer is not just pointing to one object, but to an array
      of objects: you put a set of empty square brackets in front of the
      pointer to be deleted:
      -->
      <para>
	Una vez que se ha obtenido un nuevo espacio de almacenamiento,
	los datos que estaban en el antiguo se deben copiar al
	nuevo. Esto se hace, nuevamente, en un bucle, utilizando la
	notación de índexado de arrays, copiando un byte en cada
	iteración del bucle. Una vez finalizada esta copia, ya no se
	necesitan los datos que están en el espacio de almacenamiento
	original por lo que se pueden liberar de la memoria para que
	otras partes del programa puedan usarlo cuando lo necesiten. La
	palabra reservada <kw>delete</kw> es el complemento de
	<kw>new</kw> y se debe utilizar sobre todas aquellas variables a
	las cuales se les haya asignado memoria con <kw>new</kw>. (Si se
	olvida de utilizar <kw>delete</kw> esa memoria queda
	in-utilizable. Si estas fugas de memoria (<foreignphrase>memory
	leak</foreignphrase>) son demasiado abundantes, la memoria
	disponible se acabará.)  Existe una sintaxis especial cuando se
	libera un array. Es como si recordara al compilador que ese
	puntero no apunta sólo a un objeto, sino a un array de objetos;
	se deben poner un par de corchetes delante del puntero que se
	quiere liberar:
      </para>

<programlisting>
delete []myArray;
</programlisting>

      <!--
      Once the old storage has been deleted, the pointer to the new storage
      can be assigned to the storage pointer, the quantity is adjusted, and
      inflate( ) has completed its job.
      -->
      <para>
	Una vez liberado el antiguo espacio de almacenamiento, se puede
        asignar el puntero del nuevo espacio de memoria al puntero
        <varname>storage</varname>, se actualiza
        <varname>quantity</varname> y con eso
        <function>inflate()</function> ha terminado su trabajo.
      </para>



      <!-- FIXME: en el siguiente párrafo traduje "heap compaction"
      como "defragmentación del heap" y "heap compactor" como
      "defragmentador del heap".
      -->


      <!-- Note that the heap manager is fairly primitive. It gives you
      chunks of memory and takes them back when you delete them. There's
      no inherent facility for heap compaction, which compresses the
      heap to provide bigger free chunks. If a program allocates and
      frees heap storage for a while, you can end up with a fragmented
      heap that has lots of memory free, but without any pieces that are
      big enough to allocate the size you're looking for at the
      moment. A heap compactor complicates a program because it moves
      memory chunks around, so your pointers won't retain their proper
      values. Some operating environments have heap compaction built in,
      but they require you to use special memory handles (which can be
      temporarily converted to pointers, after locking the memory so the
      heap compactor can't move it) instead of pointers. You can also
      build your own heap-compaction scheme, but this is not a task to
      be undertaken lightly.  -->
      <para>
	En este punto es bueno notar que el administrador de memoria del
	montículo> es bastante primitivo. Nos facilita trozos de memoria
	cuando se lo pedimos con <kw>new</kw> y los libera cuando
	invocamos a <kw>delete</kw>. Si un programa asigna y libera
	memoria muchas veces, terminaremos con un montículo
	<emphasis>fragmentado</emphasis>, es decir un montículo en el
	que si bien puede haber memoria libre utilizable, los trozos de
	memoria están divididos de tal modo que no exista un trozo que
	sea lo suficientemente grande para las necesidades concretas en
	un momento dado. Lamentablemente no existe una capacidad
	inherente del lenguaje para efectuar <emphasis>defragmentaciones
	del montículo</emphasis>. Un defragmentador del montículo
	complica las cosas dado que tiene que mover pedazos de memoria,
	y por lo tanto, hacer que los punteros dejen de apuntar a
	valores válidos. Algunos entornos operativos vienen con este
	tipo de facilidades pero obligan al programador a utilizar
	manejadores de memoria especiales en lugar de punteros (estos
	manipuladores se pueden convertir temporalmente en punteros una
	vez bloqueada la memoria para que el defragmentador del
	montículo no la modifique). También podemos construir nosotros
	mismos uno de estos artilugios, aunque no es una tarea sencilla.
      </para>

      <!-- When you create a variable on the stack at compile-time, the
      storage for that variable is automatically created and freed by
      the compiler. The compiler knows exactly how much storage is
      needed, and it knows the lifetime of the variables because of
      scoping. With dynamic memory allocation, however, the compiler
      doesn't know how much storage you're going to need, and it doesn't
      know the lifetime of that storage. That is, the storage doesn't
      get cleaned up automatically. Therefore, you're responsible for
      releasing the storage using delete, which tells the heap manager
      that storage can be used by the next call to new. The logical
      place for this to happen in the library is in the cleanup( )
      function because that is where all the closing-up housekeeping is
      done.  -->
      <para>
	Cuando creamos una variable en la pila en tiempo de compilación,
	el mismo compilador es quien se encarga de crearla y liberar la
	memoria ocupada por ella automáticamente. Conoce exactamente el
	tamaño y la duración de este tipo de variables dada por las
	reglas de ámbito. Sin embargo, en el caso de las variables
	almacenadas dinámicamente, el compilador no poseerá información
	ni del tamaño requerido por las mismas, ni de su duración. Esto
	significa que el compilador no puede encargarse de liberar
	automáticamente la memoria ocupada por este tipo de variables y
	de aquí que el responsable de esta tarea sea el programador (o
	sea usted). Para esto se debe utilizar <kw>delete</kw>, lo cual
	le indica al administrador del montículo que ese espacio de
	memoria puede ser utilizado por próximas llamadas a
	<kw>new</kw>. En nuestra librería de ejemplo, el lugar lógico
	para esta tarea es la función <function>cleanup()</function>
	dado que allí es dónde se deben realizar todas las labores de
	finalización de uso del objeto.
      </para>

      <!-- To test the library, two CStashes are created. The first
      holds ints and the second holds arrays of 80 chars: -->
      <para>
	Para probar la librería se crean dos <type>Cstash</type>, uno
        que almacene enteros y otro para cadenas de 80 caracteres:
      </para>


//: V1C04:CLibTest.cpp


      <!-- Following the form required by C, all the variables are
      created at the beginning of the scope of main( ). Of course, you
      must remember to initialize the CStash variables later in the
      block by calling initialize( ). One of the problems with C
      libraries is that you must carefully convey to the user the
      importance of the initialization and cleanup functions. If these
      functions aren't called, there will be a lot of
      trouble. Unfortunately, the user doesn't always wonder if
      initialization and cleanup are mandatory. They know what they want
      to accomplish, and they're not as concerned about you jumping up
      and down saying, 'Hey, wait, you have to do this first!' Some
      users have even been known to initialize the elements of a
      structure themselves. There's certainly no mechanism in C to
      prevent it (more foreshadowing).  -->
      <para>
	Dado que debemos respetar la sintaxis de C, todas las variables
        se deben declarar al comienzo de
        <function>main()</function>. Obviamente, no nos podemos olvidar
        de inicializar todas las variables <type>Cstash</type> más
        adelante en el bloque main(), pero antes de usarlas, llamando a
        <function>initialize()</function>. Uno de los problemas con las
        librerías en C es que uno debe asegurarse de convencer al
        usuario de la importancia de las funciones de inicialización y
        destrucción.  ¡Habrá muchos problemas si estas funciones se
        omiten!  Lamentablemente el usuario no siempre se preguntará si
        la inicialización y el limpiado de los objetos son
        obligatorios. Ellos le darán importancia a lo que
        <emphasis>ellos</emphasis> quieren hacer y no nos darán tanta
        importancia a nosotros (el programador de la librería) cuando
        les digamos <quote>¡Hey! ¡espera un poco! ¡Debes hacer
        <emphasis>esto</emphasis> primero!</quote>. Otro problema que
        puede presentarse es el hecho de que algunos usuarios quieran
        inicializar los elementos (datos internos) de una estructura por
        su cuenta. En C no hay un mecanismo para prevenir este tipo de
        conductas (más presagios de los temás que vendrán...).
      </para>

      <!-- The intStash is filled up with integers, and the stringStash
      is filled with character arrays. These character arrays are
      produced by opening the source code file, CLibTest.cpp, and
      reading the lines from it into a string called line, and then
      producing a pointer to the character representation of line using
      the member function c_str( ).  -->
      <para>
	La <varname>intStash</varname> se va llenando con enteros
        mientras que el <varname>stringStash</varname> se va llenando
        con arrays de caracteres. Estos arrays de caracteres son
        producidos leyendo el archivo fuente
        <filename>CLibTest.cpp</filename> y almacenando las líneas de
        este archivo en el <type>string</type>
        <varname>line</varname>. Obtenemos la representación
        <quote>puntero a carácter</quote> de <varname>line</varname> con
        el método <function>c_str()</function>. </para>

  <!--
  After each Stash is loaded, it is displayed. The intStash is printed
  using a for loop, which uses count( ) to establish its limit. The
  stringStash is printed with a while, which breaks out when fetch( )
  returns zero to indicate it is out of bounds.
  -->
      <para>
	Una vez cargados los <type>Stash</type> ambos se muestran en
	pantalla. <varname>intStash</varname> se imprime usando un bucle
	<kw>for</kw> en el cual se usa <function>count()</function> para
	determinar la cantidad de elementos. El
	<varname>stringStash</varname> se muestra utilizando un bucle
	<kw>while</kw> dentro del cual se va llamando a
	<function>fetch()</function>. Cuando esta función devuelve cero
	se rompe el bucle ya que esto significará que se han sobrepasado
	los límites de la estructura.
      </para>

      <!-- You'll also notice an additional cast in -->
      <para>
	El lector también pudo haber visto un molde adicional en la
	línea:
      </para>


<programlisting>
cp = (char*)fetch(&amp;stringStash, i++)
</programlisting>


      <!-- This is due to the stricter type checking in C++, which does
      not allow you to simply assign a void* to any other type (C allows
      this).  Bad guesses -->
      <para>
	Esto se debe a la comprobación estricta de tipos en C++, que no
	permite asignar un <type>void *</type> a una variable de
	cualquier tipo, mientras que C sí lo hubiera permitido.
      </para>
    </sect2>


    <sect2>
      <title>Malas suposiciones</title>

      <!--
      There is one more important issue you should understand before we
      look at the general problems in creating a C library. Note that
      the CLib.h header file must be included in any file that refers to
      CStash because the compiler can't even guess at what that
      structure looks like. However, it can guess at what a function
      looks like; this sounds like a feature but it turns out to be a
      major C pitfall.
      -->

      <para>
	Antes de abordar los problemas generales de la creación de una
	librería C, discutiremos otro asunto importante que se debe
	tener claro. Fíjese que el archivo de cabecera
	<filename>CLib.h</filename> <emphasis>debe</emphasis> incluirse
	en cada archivo fuente que haga referencia al tipo
	<type>CStash</type> ya que el compilador no puede adivinar qué
	aspecto tiene la estructura. Sin embargo,
	<emphasis>sí</emphasis> puede adivinar el aspecto de una
	función. Aunque eso pueda parecer una ventaja, veremos que en
	realidad, es un grave problema de C.
      </para>


      <!-- Although you should always declare functions by including a
      header file, function declarations aren't essential in C. It's
      possible in C (but not in C++) to call a function that you haven't
      declared. A good compiler will warn you that you probably ought to
      declare a function first, but it isn't enforced by the C language
      standard. This is a dangerous practice, because the C compiler can
      assume that a function that you call with an int argument has an
      argument list containing int, even if it may actually contain a
      float. This can produce bugs that are very difficult to find, as
      you will see.  -->
      <para>
	Aunque siempre debería declarar las funciones incluyendo un
	archivo de cabecera, en C las declaraciones de funciones no son
	esenciales. En este lenguaje (pero no en C++), es posible llamar
	a una función que no ha sido declarada. Un buen compilador
	seguramente avisará de que deberíamos declarar la función antes
	de usarla, pero nos permitirá seguir dado que no es obligatorio
	hacerlo en C estándar. Esta es una práctica peligrosa ya que el
	compilador puede asumir que una función que ha sido llamada con
	un <type>int</type> como argumento, tenga un <type>int</type>
	como argumento cuando, en realidad, es un
	<type>float</type>. Como veremos, esto puede producir errores
	que pueden ser muy difíciles de depurar.
      </para>


      <!-- Each separate C implementation file (with an extension of .c)
      is a translation unit. That is, the compiler is run separately on
      each translation unit, and when it is running it is aware of only
      that unit. Thus, any information you provide by including header
      files is quite important because it determines the compiler's
      understanding of the rest of your program. Declarations in header
      files are particularly important, because everywhere the header is
      included, the compiler will know exactly what to do. If, for
      example, you have a declaration in a header file that says void
      func(float), the compiler knows that if you call that function
      with an integer argument, it should convert the int to a float as
      it passes the argument (this is called promotion). Without the
      declaration, the C compiler would simply assume that a function
      func(int) existed, it wouldn't do the promotion, and the wrong
      data would quietly be passed into func( ).  -->
      <para>
	Se dice que cada archivo de implementación C (los archivos de
	extensión <filename>.c</filename>) es una unidad de traducción
	(<foreignphrase>translation unit</foreignphrase>). El compilador
	se ejecuta independientemente sobre cada unidad de traducción
	ocupándose, en ese momento, solamente en ese archivo. Por eso,
	la información que le demos al compilador por medio de los
	archivos de cabecera es muy importante dado que determina la
	forma enq que ese archivo se relaciona con las demás partes del
	programa. Por eso motivo, las declaraciones en los archivos de
	cabecera son particularmente importantes dado que, en cada lugar
	que se incluyen, el compilador sabrá exactamente qué hacer. Por
	ejemplo, si en un archivo de cabecera tenemos la declaración
	<function>void func(float) </function>, si llamamos a
	<function>func()</function> con un <type>int</type> como
	argumento, el compilador sabrá que deberá convertir el
	<type>int</type> a <type>float</type> antes de pasarle el valor
	a la función (a esto se le llama <emphasis>promoción</emphasis>
	de tipos). Sin la declaración, el compilador asumiría que la
	función tiene la forma <function>func(int)</function>, no
	realizaría la promoción y pasaría, por lo tanto, datos
	incorrectos a la función.
      </para>


      <!-- For each translation unit, the compiler creates an object
      file, with an extension of .o or .obj or something similar. These
      object files, along with the necessary start-up code, must be
      collected by the linker into the executable program. During
      linking, all the external references must be resolved. For
      example, in CLibTest.cpp, functions such as initialize( ) and
      fetch( ) are declared (that is, the compiler is told what they
      look like) and used, but not defined. They are defined elsewhere,
      in CLib.cpp. Thus, the calls in CLib.cpp are external
      references. The linker must, when it puts all the object files
      together, take the unresolved external references and find the
      addresses they actually refer to. Those addresses are put into the
      executable program to replace the external references.  -->
      <para>
	Para cada unidad de traducción, el compilador crea un archivo
	objeto, de extensión <filename>.o</filename>,
	<filename>.obj</filename> o algo por el estilo. Estos archivos
	objeto, junto con algo de código de arranque se unens por el
	enlazador(<foreignphrase>linker</foreignphrase>) para crear el
	programa ejecutable. Todas las referencias externas se deben
	resolver en la fase de enlazado. En archivos como
	<filename>CLibTest.cpp</filename>, se declaran funciones como
	<function>initialize()</function> y <function>fetch()</function>
	(o sea, se le informa al compilador qué forma tienen estas
	funciones), pero no se definen. Están definidas en otro lugar,
	en este caso en el archivo <filename>CLib.cpp</filename>. De ese
	modo, las llamadas que se hacen en
	<filename>CLibTest.cpp</filename> a estas funciones son
	referencias externas. Cuando se unen los archivos objeto para
	formar el programa ejecutable, el enlazador debe, para cada
	referencia externa no resuelta, encontrar la dirección a la que
	hace referencia y reemplazar cada referencia externa con su
	dirección correspondiente.
      </para>

      <!-- It's important to realize that in C, the external references
      that the linker searches for are simply function names, generally
      with an underscore in front of them. So all the linker has to do
      is match up the function name where it is called and the function
      body in the object file, and it's done. If you accidentally made a
      call that the compiler interpreted as func(int) and there's a
      function body for func(float) in some other object file, the
      linker will see _func in one place and _func in another, and it
      will think everything's OK. The func( ) at the calling location
      will push an int onto the stack, and the func( ) function body
      will expect a float to be on the stack. If the function only reads
      the value and doesn't write to it, it won't blow up the stack. In
      fact, the float value it reads off the stack might even make some
      kind of sense. That's worse because it's harder to find the bug.
      What's wrong?  -->
      <para>
	Es importante señalar que en C, estas referencias externas que
	el enlazador busca son simples nombres de funciones,
	generalmente precedidos por un guión bajo. De esta forma, la
	única tarea del enlazador es hacer corresponder el nombre de la
	función que se llama, con el cuerpo (definición, código) de la
	función del archivo objeto, en el lugar exacto de la llamada a
	dicha función. Si, por ejemplo, accidentalmente hacemos una
	llamada a una función que el compilador interprete como
	<function>func(int)</function> y existe una definición de
	función para <function>func(float)</function> en algún archivo
	objeto, el enlazador verá <function>_func</function> en un lugar
	y <function>_func</function> en otro, por lo que
	<emphasis>pensará</emphasis> que todo está bien. En la llamada a
	<function>func()</function> se pasará un <type>int</type> en la
	pila pero el cuerpo de la función <function>func()</function>
	esperará que la pila tenga un <type>float</type>. Si la función
	sólo lee el valor de este dato y no lo escribe, la pila no
	sufrirá datos. De hecho, el supuesto <type>float</type> leído de
	la pila puede tener algo de sentido: la función seguirá
	funcionando aunque sobre basura, y es por eso que los fallos
	originadas por esta clase de errores son muy difíciles de
	encontrar.
      </para>
    </sect2>
  </sect1>


  <sect1>
    <!-- What's wrong? -->
    <title>¿Qué tiene de malo?</title>

    <!-- We are remarkably adaptable, even in situations in which
    perhaps we shouldn't adapt. The style of the CStash library has been
    a staple for C programmers, but if you look at it for a while, you
    might notice that it's rather . . . awkward. When you use it, you
    have to pass the address of the structure to every single function
    in the library. When reading the code, the mechanism of the library
    gets mixed with the meaning of the function calls, which is
    confusing when you're trying to understand what's going on.  -->
    <para>
      Somos seres realmente destinados a la adaptación, incluso a las
      que quizá <emphasis>no deberíamos</emphasis> adaptarnos. El estilo
      de la librería <type>CStash</type> ha sido un modelo a seguir para
      los programadores en C durante mucho tiempo. Sin embargo, si nos
      ponemos a examinarla por un momento, nos daremos cuenta de que
      utilizar esta librería puede resultar incómodo. Cuando la usamos
      debemos, por ejemplo, pasar la dirección de la estructura a cada
      función de la librería. Por eso, cuando leemos el código, los
      mecanismos de la librería se mezclan con el significado de las
      llamadas a las funciones, lo cual dificulta la comprecsión del
      programa.
    </para>


    <!-- One of the biggest obstacles, however, to using libraries in C
    is the problem of name clashes. C has a single name space for
    functions; that is, when the linker looks for a function name, it
    looks in a single master list. In addition, when the compiler is
    working on a translation unit, it can work only with a single
    function with a given name.  -->
    <para>
      Sin embargo, uno de los mayores obstáculos al trabajar con
      librerías en C es el problema llamado <emphasis>conflicto de
      nombres</emphasis> (<foreignphrase>name
      clashes</foreignphrase>). C trabaja con un único espacio de
      nombres de funciones. Esto significa que, cuando el enlazador
      busca por el nombre de una función, lo hace en una única lista de
      nombres maestra. Además, cuando el compilador trabaja sobre una
      unidad de traducción, un nombre de función sólo puede hacer
      referencia a una única función con ese nombre.
    </para>


    <!-- Now suppose you decide to buy two libraries from two different
    vendors, and each library has a structure that must be initialized
    and cleaned up. Both vendors decided that initialize( ) and cleanup(
    ) are good names. If you include both their header files in a single
    translation unit, what does the C compiler do? Fortunately, C gives
    you an error, telling you there's a type mismatch in the two
    different argument lists of the declared functions. But even if you
    don't include them in the same translation unit, the linker will
    still have problems. A good linker will detect that there's a name
    clash, but some linkers take the first function name they find, by
    searching through the list of object files in the order you give
    them in the link list. (This can even be thought of as a feature
    because it allows you to replace a library function with your own
    version.)  -->
    <para>
      Supongamos que compramos dos librerías de diferentes proveedores y
      que cada librería consta de una estructura que debe inicializar y
      destruir. Supongamos que cada proveedor ha decidido nombrar a
      dichas operaciones <function>initialize()</function> y
      <function>cleanup()</function>. ¿Cómo se comportaría el compilador
      si incluyéramos los archivos de cabecera de ambas librerías en la
      misma unidad de traducción? Afortunadamente, el compilador C dará
      un mensaje de error diciéndonos que hay una incoherencia de tipos
      en las listas de argumentos de ambas declaraciones. No obstante,
      aunque no incluyamos los archivos de cabecera en la unidad de
      traducción igual tendremos problemas con el enlazador. Un buen
      enlazador detectará y avisará cuando se produzca uno de estos
      conflictos de nombres. Sin embargo, hay otros que simplemente
      tomarán el primer nombre de la función que encuentren, buscando en
      los archivos objeto en el orden en el que fueron pasados en la
      lista de enlazado. (Este comportamiento se puede considerar
      como una ventaja ya que permite reemplazar las funciones de
      las librerías ajenas con funciones propias.)
    </para>

    <!-- In either event, you can't use two C libraries that contain a
    function with the identical name. To solve this problem, C library
    vendors will often prepend a sequence of unique characters to the
    beginning of all their function names. So initialize( ) and cleanup(
    ) might become CStash_initialize( ) and CStash_cleanup( ). This is a
    logical thing to do because it 'decorates' the name of the struct
    the function works on with the name of the function.  -->
    <para>
      En cualquiera de los dos casos, llegamos a la conclusión de que en
      C es imposible usar dos bibliotecas en las cuales existan
      funciones con nombres idénticos. Para solucionar este problema,
      los proveedores de librerías en C ponen un prefijo único a todas
      las funciones de la librería. En nuestro ejemplo, las funciones
      <function>initialize()</function> y <function>cleanup()</function>
      habría que renombrarlas como
      <function>CStash_initialize()</function> y
      <function>CStash_cleanup()</function>. Esta es una técnica lógica:
      decoramos los nombres de las funciones con el nombre de la
      estructura sobre la cual trabajan.
    </para>

    <!-- Now it's time to take the first step toward creating classes in
    C++. Variable names inside a struct do not clash with global
    variable names. So why not take advantage of this for function
    names, when those functions operate on a particular struct? That is,
    why not make functions members of structs?  -->
    <para>
      Este es el momento de dirigir nuestros pasos a las primeras
      nociones de construcción de clases en C++. Como el lector ha de
      saber, las variables declaradas dentro de una estructura no tienen
      conflictos de nombres con las variables globales. ¿Por qué,
      entonces, no aprovechar esta característica de las variables para
      evitar los conflictos de nombres de funciones declarándolas dentro
      de la estructura sobre la cual operan? O sea, ¿por qué no hacer
      que las funciones sean también miembros de las estructuras?
    </para>
  </sect1>


  <sect1>
    <!-- The basic object -->
    <title>El objeto básico</title>


    <!-- Step one is exactly that. C++ functions can be placed inside
    structs as 'member functions.' Here's what it looks like after
    converting the C version of CStash to the C++ Stash: -->
    <para>
      Nuestro primer paso será exactamente ese.  Meter las funciones C++
      dentro de las estructuras como <quote>funciones
      miembro</quote>. Éste es el aspecto que tiene la estructura una
      vez realizados estos cambios de la versión C de la <type>CStash</type>
      a la versión en C++, a la que llamaremos <type>Stash</type>:
    </para>


//: V1C04:CppLib.h


    <!-- First, notice there is no typedef. Instead of requiring you to
    create a typedef, the C++ compiler turns the name of the structure
    into a new type name for the program (just as int, char, float and
    double are type names).  -->
    <para>
      La primera diferencia que puede notarse es que no se usa
      <kw>typedef</kw>. A diferencia de C que requiere el uso de
      <kw>typedef</kw> para crear nuevos tipos de datos, el compilador
      de C++ hará que el nombre de la estructura sea un nuevo tipo de
      dato automáticamente en el programa (tal como los nombres de
      tipos de datos <type>int</type>, <type>char</type>,
      <type>float</type> y <type>double</type>).
    </para>

    <!-- All the data members are exactly the same as before, but now
    the functions are inside the body of the struct. In addition, notice
    that the first argument from the C version of the library has been
    removed. In C++, instead of forcing you to pass the address of the
    structure as the first argument to all the functions that operate on
    that structure, the compiler secretly does this for you. Now the
    only arguments for the functions are concerned with what the
    function does, not the mechanism of the function's operation.  -->
    <para>
      Todos los datos miembros de la estructura están declarados igual
      que antes; sin embargo, ahora las funciones están declaradas
      dentro del cuerpo de la <kw>struct</kw>. Más aún, fíjese que el primer
      argumento de todas las funciones ha sido eliminado. En C++,
      en lugar de forzar al usuario a que pase la dirección de la
      estructura sobre la que trabaja una función como primer argumento,
      el compilador hará este trabajo, secretamente. Ahora sólo
      debe preocuparse por los argumentos que le dan sentido a lo
      que la función <emphasis>hace</emphasis> y no de los mecanismos
      internos de la función.
    </para>


    <!--
    It's important to realize that the function code is effectively the
    same as it was with the C version of the library. The number of
    arguments is the same (even though you don't see the structure address
    being passed in, it's still there), and there's only one function body
    for each function. That is, just because you say
    -->
    <para>
      Es importante darse cuenta de que el código generado por estas
      funciones es el mismo que el de las funciones de la librería al
      estilo C. El número de argumentos es el mismo (aunque no se le
      pase la dirección de la estructura como primer argumento, en
      realidad sí se hace) y sigue existiendo un único cuerpo
      (definición) de cada función. Esto último quiere decir que, aunque
      declare múltiples variables
    </para>


<programlisting>Stash A, B, C;</programlisting>

    <!-- doesn't mean you get a different add( ) function for each
    variable. -->
    <para>
      no existirán múltiples definiciones de, por ejemplo, la
      función <function>add()</function>, una para cada variable.
    </para>


  <!--
  So the code that's generated is almost identical to what you would have
  written for the C version of the library. Interestingly enough, this
  includes the 'name decoration' you probably would have done to produce
  Stash_initialize( ), Stash_cleanup( ), and so on. When the function name
  is inside the struct, the compiler effectively does the same
  thing. Therefore, initialize( ) inside the structure Stash will not
  collide with a function named initialize( ) inside any other structure,
  or even a global function named initialize( ). Most of the time you
  don't have to worry about the function name decoration ? you use the
  undecorated name. But sometimes you do need to be able to specify that
  this initialize( ) belongs to the struct Stash, and not to any other
  struct. In particular, when you're defining the function you need to
  fully specify which one it is. To accomplish this full specification,
  C++ has an operator (::) called the scope resolution operator (named so
  because names can now be in different scopes: at global scope or within
  the scope of a struct). For example, if you want to specify initialize(
  ), which belongs to Stash, you say Stash::initialize(int size). You can
  see how the scope resolution operator is used in the function
  definitions:
  -->
    <para>
      De modo que el código generado es casi idéntico al que hubiese
      escrito para una versión en C de la librería, incluyendo la
      <quote>decoración de nombres</quote> ya mencionada para evitar los
      conflictos de nombres, nombrando a las funciones
      <function>Stash_initialize()</function>,
      <function>Stash_cleanup()</function> y demás. Cuando una función
      está dentro de una estructura, el compilador C++ hace lo mismo y
      por eso, una función llamada <function>initialize()</function>
      dentro de una estructura no estará en conflicto con otra función
      <function>initialize()</function> dentro de otra estructura o con
      una función <function>initialize()</function> global. De este
      modo, en general no tendrá que preocuparse por los conflictos de
      nombres de funciones - use el nombre sin decoración. Sin embargo,
      habrá situaciones en las que deseará especificar, por ejemplo,
      esta <function>initialize()</function> pertenece a la estructura
      <type>Stash</type> y no a ninguna otra. En particular, cuando
      defina la función, necesita especificar a qué estructura pertenece
      para lo cual, en C++ cuenta con el operador <oper>::</oper>
      llamado operador de resolución de ámbito (ya que ahora un nombre
      puede estar en diferentes ámbitos: el del ámbito global o dentro
      del ámbito de una estructura. Por ejemplo, si quiere referirse
      a una función <function>initialize()</function> que se encuentra
      dentro de la estructura <type>Stash</type> lo podrá hacer con
      la expresión <function>Stash::initialize(int size)</function>. A
      continuación podrá ver cómo se usa el operador de resolución de
      ámbito para definir funciones:
    </para>

    <!--  [FIXME: traducir el siguiente programlisting] -->


//: V1C04:CppLib.cpp


  <!--
  There are several other things that are different between C and
  C++. First, the declarations in the header files are required by the
  compiler. In C++ you cannot call a function without declaring it
  first. The compiler will issue an error message otherwise. This is an
  important way to ensure that function calls are consistent between the
  point where they are called and the point where they are defined. By
  forcing you to declare the function before you call it, the C++ compiler
  virtually ensures that you will perform this declaration by including
  the header file. If you also include the same header file in the place
  where the functions are defined, then the compiler checks to make sure
  that the declaration in the header and the function definition match
  up. This means that the header file becomes a validated repository for
  function declarations and ensures that functions are used consistently
  throughout all translation units in the project.
  -->
    <para>
      Hay muchas otras cosas que difieres entre C y C++. Para empezar,
      el compilador <emphasis>requiere</emphasis> que declare las
      funciones en los archivos de cabecera: en C++ no podrá llamar a
      una función sin haberla declarado antes y si no se cumple esta
      regla el compilador dará un error. Esta es una forma importante de
      asegurar que las llamadas a una función son consistentes entre el
      punto en que se llama y el punto en que se define. Al forzar a
      declarar una función antes de usarla, el compilador de C++
      prácticamente se asegura de que realizará esa declaración por
      medio de la inclusión de un fichero de cabecera. Además, si
      también incluye el mismo fichero de cabecera en el mismo lugar
      donde se defines las funciones, el compilador verificará que las
      declaraciones del archivo cabecera y las definiciones
      coinciden. Puede decirse entonces que, de algún modo, los
      ficheros de cabecera se vuelven un repositorio de validación de
      funciones y permiten asegurar que las funciones se usan
      de modo consistente en todas las unidades de traducción del
      proyecto.
    </para>


  <!--
  Of course, global functions can still be declared by hand every place
  where they are defined and used. (This is so tedious that it becomes
  very unlikely.) However, structures must always be declared before they
  are defined or used, and the most convenient place to put a structure
  definition is in a header file, except for those you intentionally hide
  in a file.
  -->
    <para>
      Obviamente, las funciones globales se pueden seguir declarando a
      mano en aquellos lugares en las que se definen y usan (Sin
      embargo, esta práctica es tan tediosa que está en desuso.)  De
      cualquier modo, las estructuras siempre se deben declarar antes de
      ser usadas y el mejor lugar para esto es un fichero de cabecera,
      exceptuando aquellas que queremos esconder intencionalmente en
      otro fichero.
    </para>

  <!--
  You can see that all the member functions look almost the same as when
  they were C functions, except for the scope resolution and the fact that
  the first argument from the C version of the library is no longer
  explicit. It's still there, of course, because the function has to be
  able to work on a particular struct variable. But notice, inside the
  member function, that the member selection is also gone! Thus, instead
  of saying s?>size = sz; you say size = sz; and eliminate the tedious
  s?>, which didn't really add anything to the meaning of what you were
  doing anyway. The C++ compiler is apparently doing this for you. Indeed,
  it is taking the 'secret' first argument (the address of the structure
  that we were previously passing in by hand) and applying the member
  selector whenever you refer to one of the data members of a struct. This
  means that whenever you are inside the member function of another
  struct, you can refer to any member (including another member function)
  by simply giving its name. The compiler will search through the local
  structure's names before looking for a global version of that
  name. You'll find that this feature means that not only is your code
  easier to write, it's a lot easier to read.
  -->
    <para>
      Se puede ver que todas las funciones miembro (métodos) tienen casi
      la misma forma que sus versiones respectivas en C. Las únicas
      diferencias son su ámbito de resolución y el hecho de que el
      primer argumento ya no aparece explícito en el prototipo de la
      función. Por supuesto que sigue ahí ya que la función debe ser
      capaz de trabajar sobre una variable <kw>struct</kw> en
      particular. Sin embargo, fíjese también que, dentro del método, la
      selección de esta estructura en particular también ha
      desaparecido! Así, en lugar de decir <code>s->size = sz;</code>
      ahora dice <code>size = sz;</code> eliminando el tedioso
      <code>s-></code> que en realidad no aportaba nada al significado
      semántico de lo que estaba escribiendo. Aparentemente, el
      compilador de C++ está realizando estas tareas por el
      programador. De hecho, está tomando el primer argumento
      <quote>secreto</quote> (la dirección de la estructura que antes
      tenía que pasar a mano) y aplicándole el selector de miembro (->)
      siempre que escribe el nombre de uno de los datos miembro. Eso
      significa que, siempre y cuando esté dentro de la definición de
      una método de una estructura puede hacer referencia a cualquier
      otro miembro (incluyendo otro método) simplemente dando su
      nombre. El compilador buscará primero en los nombres locales de la
      estructura antes de buscar en versiones más globales de dichos
      nombres. El lector podrá descubrir que esta característica no sólo
      agiliza la escritura del código, sino que también hace la lectura
      del mismo mucho más sencilla.
    </para>

  <!--
  But what if, for some reason, you want to be able to get your hands on
  the address of the structure? In the C version of the library it was
  easy because each function's first argument was a CStash* called s. In
  C++, things are even more consistent. There's a special keyword, called
  this, which produces the address of the struct. It's the equivalent of
  the 's' in the C version of the library. So we can revert to the C
  style of things by saying
  -->
    <para>
      Pero qué pasaría si, por alguna razón,
      <emphasis>quisiera</emphasis> hacer referencia a la dirección de
      memoria de la estructura. En la versión en C de la librería ésta
      se podía obtener fácilmente del primer argumento de cualquier
      función. En C++ la cosa es más consistente: existe la palabra
      reservada <literal>this</literal> que produce la dirección de la
      variable <kw>struct</kw> actual. Es el equivalente a la expresión
      <varname>s</varname> de la versión en C de la librería. De modo
      que, podremos volver al estilo de C escribiendo
    </para>

<programlisting>
this->size = Size;
</programlisting>


  <!--
  The code generated by the compiler is exactly the same, so you don't
  need to use this in such a fashion; occasionally, you'll see code where
  people explicitly use this-> everywhere but it doesn't add anything to
  the meaning of the code and often indicates an inexperienced
  programmer. Usually, you don't use this often, but when you need it,
  it's there (some of the examples later in the book will use this).
  -->
    <para>
      El código generado por el compilador será exactamente el mismo por
      lo que no es necesario usar <literal>this</literal> en estos
      casos. Ocasionalmente, podrá ver por ahí código dónde la gente usa
      <literal>this</literal> en todos sitios sin agregar nada al
      significado del código (esta práctica es indicio de programadores
      inexpertos). Por lo general, <literal>this</literal> no se usa muy
      a menudo pero, cuando se necesite siempre estará allí (en
      ejemplos posteriores del libro verá más sobre su uso).
    </para>

  <!--
  There's one last item to mention. In C, you could assign a void* to any
  other pointer like this:
  -->
    <para>
      Queda aún un último tema que tocar. En C, se puede asignar un
      <type>void *</type> a cualquier otro puntero, algo como esto:
    </para>

<programlisting>
int i = 10;
void* vp = &amp;i; // OK tanto en C como en C++
int* ip = vp; // Sólo aceptable en C
</programlisting>

  <!--
  and there was no complaint from the compiler. But in C++, this statement
  is not allowed. Why? Because C is not so particular about type
  information, so it allows you to assign a pointer with an unspecified
  type to a pointer with a specified type. Not so with C++. Type is
  critical in C++, and the compiler stamps its foot when there are any
  violations of type information. This has always been important, but it
  is especially important in C++ because you have member functions in
  structs. If you could pass pointers to structs around with impunity in
  C++, then you could end up calling a member function for a struct that
  doesn't even logically exist for that struct! A real recipe for
  disaster. Therefore, while C++ allows the assignment of any type of
  pointer to a void* (this was the original intent of void*, which is
  required to be large enough to hold a pointer to any type), it will not
  allow you to assign a void pointer to any other type of pointer. A cast
  is always required to tell the reader and the compiler that you really
  do want to treat it as the destination type.
  -->
    <para>
      y no habrá ningún tipo de queja por parte de compilador. Sin
      embargo, en C++, lo anterior no está permitido. ¿Por qué? Porque C
      no es tan estricto con los tipos de datos y permite asignar un
      puntero sin un tipo específico a un puntero de un tipo bien
      determinado. No así C++, en el cual la verificación de tipos es
      crítica y el compilador se detendrá quejándose en cualquier
      conflicto de tipos. Esto siempre ha sido importante, pero es
      especialmente importante en C++ ya que dentro de las estructuras
      puede hacer métodos. Si en C++ estuviera permitido pasar punteros
      a estructuras con impunidad en cuanto a conflicto de tipos,
      ¡podría terminar llamando a un método de una estructura en la cual
      no existiera dicha función miembro! Una verdadera fórmula para el
      desastre. Así, mientras C++ sí deja asignar cualquier puntero a un
      <type>void *</type> (en realidad este es el propósito original del
      puntero a <type>void</type>: que sea suficientemente largo como
      para apuntar a cualquier tipo) no permite asignar un <type>void
      *</type> a cualquier otro tipo de puntero. Para ello se requiere
      un molde que le indique tanto al lector como al compilador que
      realmente quiere tratarlo como el puntero destino.
    </para>

  <!--
  This brings up an interesting issue. One of the important goals for C++
  is to compile as much existing C code as possible to allow for an easy
  transition to the new language. However, this doesn't mean any code
  that C allows will automatically be allowed in C++. There are a number
  of things the C compiler lets you get away with that are dangerous and
  error-prone. (We'll look at them as the book progresses.) The C++
  compiler generates warnings and errors for these situations. This is
  often much more of an advantage than a hindrance. In fact, there are
  many situations in which you are trying to run down an error in C and
  just can't find it, but as soon as you recompile the program in C++,
  the compiler points out the problem! In C, you'll often find that you
  can get the program to compile, but then you have to get it to work. In
  C++, when the program compiles correctly, it often works, too! This is
  because the language is a lot stricter about type.
  -->
    <para>
      Y esto nos lleva a discutir un asunto interesante. Uno de los
      objetivos importantes de C++ es poder compilar la mayor cantidad
      posible de código C para así, permitir una fácil transición al
      nuevo lenguaje. Sin embargo, eso no significa, como se ha visto
      que cualquier segmento de código que sea válido en C, será
      permitido automáticamente en C++. Hay varias cosas que un
      compilador de C permite hacer que son potencialmente peligrosas y
      propensas a generar errores (verá ejemplos de a lo largo de
      libro). El compilador de C++ genera errores y avisos en este tipo
      de situaciones y como verá eso es más una ventaja que un obstáculo
      a pesar de su naturaleza restrictiva. ¡De hecho, existen muchas
      situaciones en las cuales tratará de detectar sin éxito un error
      en C y cuando recompiles el programa con un compilador de C++ éste
      avisa exactamente de la causa del problema!. En C, muy a menudo
      ocurre que para que un programa funcione correctamente, además de
      compilarlo, luego debe <emphasis>hacer que ande</emphasis>. ¡En
      C++, por el contrario, verá que muchas veces si un programa
      compila correctamente es probable que funcione bien!  Esto
      se debe a que este último lenguaje es mucho más estricto respecto
      a la comprobación de tipos.
    </para>

  <!--
  You can see a number of new things in the way the C++ version of Stash
  is used in the following test program:
  -->
    <para>
      En el siguiente programa de prueba podrá apreciar cosas nuevas con
      respecto a cómo se utiliza la nueva versión de la
      <type>Stash</type>:
    </para>


//: V1C04:CppLibTest.cpp


  <!--
  One thing you'll notice is that the variables are all defined 'on the
  fly' (as introduced in the previous chapter). That is, they are defined
  at any point in the scope, rather than being restricted ? as in C ? to
  the beginning of the scope.
  -->
    <para>
      Una de las cosas que el lector habrá podido observar en el código
      anterior es que las variables se definen <quote>al vuelo</quote>,
      o sea (como se introdujo en el capítulo anterior) en cualquier
      parte de un bloque y no necesariamente -como en C- al comienzo
      de los mismos.
    </para>

  <!--
  The code is quite similar to CLibTest.cpp, but when a member function is
  called, the call occurs using the member selection operator '.'
  preceded by the name of the variable. This is a convenient syntax
  because it mimics the selection of a data member of the structure. The
  difference is that this is a function member, so it has an argument
  list.
  -->
    <para>
      El código es bastante similar al visto en
      <filename>CLibTest.cpp</filename> con la diferencia de que, cuando
      se llama a un método, se utiliza el operador de selección de
      miembro '<oper>.</oper>' precedido por el nombre de la
      variable. Esta es una síntaxis conveniente ya que imita a la
      selección o acceso de un dato miembro de una estructura. La única
      diferencia es que, al ser un método, su llamada implica una lista
      de argumentos.
    </para>

  <!--
  Of course, the call that the compiler actually generates looks much more
  like the original C library function. Thus, considering name decoration
  and the passing of this, the C++ function call
  intStash.initialize(sizeof(int), 100) becomes something like
  Stash_initialize(&intStash, sizeof(int), 100). If you ever wonder
  what's going on underneath the covers, remember that the original C++
  compiler cfront from AT&T produced C code as its output, which was then
  compiled by the underlying C compiler. This approach meant that cfront
  could be quickly ported to any machine that had a C compiler, and it
  helped to rapidly disseminate C++ compiler technology. But because the
  C++ compiler had to generate C, you know that there must be some way to
  represent C++ syntax in C (some compilers still allow you to produce C
  code).
  -->
    <para>
      Tal y cómo se dijo antes, la llamada que el compilador hace genera
      <emphasis>realmente</emphasis> es mucho más parecida a la llamada
      a la función de la librería en C. Considere la decoración de
      nombres y el paso del puntero <varname>this</varname>: la llamada
      en C++ de <function>intStash.initialize(sizeof(int),
      100)</function> se transformará en algo parecido a
      <function>Stash_initialize(&amp;intStash, sizeof(int),
      100)</function>. Si el lector se pregunta qué es lo que sucede
      realmente debajo del envoltorio, debería recordar que el
      compilador original de C++ <application>cfront</application> de
      AT&amp;T producía código C como salida que luego debía ser
      compilada con un compilador de C para generar el ejecutable. Este
      método permitía a <application>cfront</application> ser
      rápidamente portable a cualquier máquina que soportara un
      compilador estándar de C y ayudó a la rápida difusión de C++. Dado
      que los compiladores antiguos de C++ tenían que generar código C,
      sabemos que existe una manera de representar síntaxis C++ en C
      (algunos compiladores de hoy en día aún permiten generar código
      C).
    </para>

  <!--
  There's one other change from ClibTest.cpp, which is the introduction
  of the require.h header file. This is a header file that I created for
  this book to perform more sophisticated error checking than that
  provided by assert( ). It contains several functions, including the one
  used here called assure( ), which is used for files. This function
  checks to see if the file has successfully been opened, and if not it
  reports to standard error that the file could not be opened (thus it
  needs the name of the file as the second argument) and exits the
  program. The require.h functions will be used throughout the book, in
  particular to ensure that there are the right number of command-line
  arguments and that files are opened properly. The require.h functions
  replace repetitive and distracting error-checking code, and yet they
  provide essentially useful error messages. These functions will be fully
  explained later in the book.
  -->
    <para>
      Comparando con <filename>CLibTest.cpp</filename> observará un
      cambio: la introducción del fichero de cabecera
      <filename>require.h</filename>. He creado este fichero de cabecera
      para realizar una comprobación de errores más sofisticada que la
      que proporciona <function>assert()</function>. Contiene varias
      funciones incluyendo la llamada en este último ejemplo,
      <function>assure()</function> que se usa sobre ficheros. Esta
      función verifica que un fichero se ha abierto exitosamente y en
      caso contrario reporta un aviso a la salida de error estándar (por
      lo que también necesita el nombre del fichero como segundo
      argumento) y sale del programa. Las funciones de
      <filename>require.h</filename> se usan a lo largo de este libro
      especialmente para asegurar que se ha indicado la cantidad
      correcta de argumentos en la línea de comandos y para verificar
      que los ficheros se abren correctamente. Las funciones de
      <filename>require.h</filename> reemplazan el código de detección
      de errores repetitivo y que muchas veces es causa de distracciones
      y más aún, proporcionan mensajes útiles para la detección de
      posibles errores. Estas funciones se explican detalladamente más
      adelante.
    </para>
  </sect1>


  <sect1>
    <!-- What's an object? -->
    <title>¿Qué es un objeto?</title>

    <!-- Now that you've seen an initial example, it's time to step
      back and take a look at some terminology. The act of bringing
      functions inside structures is the root of what C++ adds to C,
      and it introduces a new way of thinking about structures: as
      concepts. In C, a struct is an agglomeration of data, a way to
      package data so you can treat it in a clump. But it's hard to
      think about it as anything but a programming convenience. The
      functions that operate on those structures are
      elsewhere. However, with functions in the package, the structure
      becomes a new creature, capable of describing both
      characteristics (like a C struct does) and behaviors. The
      concept of an object, a free-standing, bounded entity that can
      remember and act, suggests itself.  -->

    <para>
      Ahora que ya se ha visto y discutido un ejemplo incial es hora
      de retroceder para definir la terminología. El acto de
      introducir funciones en las estructuras es el eje central del
      cambio que C++ propone sobre C, e eso introduce una nueva forma
      de ver las estructuras: como conceptos. En C, una estructura
      (<kw>struct</kw>) es tan sólo una agrupación de datos: una
      manera de empaquetar datos para que se puedan tratar como un
      grupo. De esta forma, cuesta hacerse a la idea de que
      representan algo más que una mera conveniencia de programación.

      Las funciones que operan sobre esas estructuras están sueltas
      por ahí. Sin embargo, con las funciones dentro del mismo paquete
      que los datos, la estructura se convierte en una nueva criatura,
      capaz de representar las características (como hacen
      las <kw>struct</kw>s de C) <emphasis>y</emphasis> los
      comportamientos. El concepto de objeto, una entidad
      independiente y bien limitada que puede
      recordar <emphasis>y</emphasis> actuar, se sugiere a si mismo
      como definición.
    </para>


  <!--
  In C++, an object is just a variable, and the purest definition is 'a
  region of storage' (this is a more specific way of saying, 'an object
  must have a unique identifier,' which in the case of C++ is a unique
  memory address). It's a place where you can store data, and it's
  implied that there are also operations that can be performed on this
  data.
  -->
  <para>
    En C++, un objeto es simplemente una variable, y la definición más
    purista es <quote>una región de almacenamiento</quote> (que es una
    forma más específica para decir <quote>un objeto debe tener un
    único identificador</quote> el cual, en el caso de C++, es una
    dirección única de memoria). Es un lugar en el cual se pueden
    almacenar datos y eso implica también operaciones que pueden
    actuar sobre esos datos.
  </para>

  <!--
  Unfortunately, there's not complete consistency across languages when
  it comes to these terms, although they are fairly well-accepted. You
  will also sometimes encounter disagreement about what an object-oriented
  language is, although that seems to be reasonably well sorted out by
  now. There are languages that are object-based, which means that they
  have objects like the C++ structures-with-functions that you've seen so
  far. This, however, is only part of the picture when it comes to an
  object-oriented language, and languages that stop at packaging functions
  inside data structures are object-based, not object-oriented.
    -->
  <para>
    Desafortunadamente no existe una consistencia completa entre los
    distintos lenguajes cuando se habla de estos términos, aunque son
    aceptados bastante bien. También se podrán encontrar discrepancias
    sobre lo que es un lenguaje orientado a objetos, aunque parece
    haber un consenso razonable hoy en día. Hay
    lenguajes <emphasis>basados en objetos</emphasis>, que cuentan con
    estructuras-con-funciones como las que ha visto aquí de C++. Sin
    embargo, esto es tan sólo una parte de lo que denomina
    un lenguaje <emphasis>orientado a objetos</emphasis>, y los
    lenguajes que solamente llegan a empaquetar las funciones
    dentro de las estructuras son lenguajes basados en objetos y no
    orientados a objetos.
  </para>
  </sect1>


  <sect1>
    <!-- Abstract data typing-->
    <title>Tipos abstractos de datos</title>

  <!--
  The ability to package data with functions allows you to create a new
  data type. This is often called encapsulation[33]. An existing data type
  may have several pieces of data packaged together. For example, a float
  has an exponent, a mantissa, and a sign bit. You can tell it to do
  things: add to another float or to an int, and so on. It has
  characteristics and behavior.
  -->

    <para>
      La habilidad para empaquetar datos junto con funciones permite
      la creación de nuevos tipos de datos. Esto se llama a menudo
      <emphasis>encapsulación</emphasis>

      <footnote>
        <para>
	  Este término puede causar debates. Algunas personas lo
          utilizan tal y como está definido aquí, aunque otras lo usan
          para describir el <emphasis>control de acceso</emphasis>,
          término que se discutirá en el siguiente capítulo.
	</para>
      </footnote>

      Un tipo de dato existente puede contener varias piezas de datos
      empaquetadas juntas. Por ejemplo, un <type>float</type> tiene un
      exponente, una mantissa y un bit de signo. Le podemos pedir que
      haga varias cosas: sumarse a otro <type>float</type> o a un
      <type>int</type>, etc. Tiene características y comportamiento.
    </para>

  <!--
  The definition of Stash creates a new data type. You can add( ), fetch(
  ), and inflate( ). You create one by saying Stash s, just as you create
  a float by saying float f. A Stash also has characteristics and
  behavior. Even though it acts like a real, built-in data type, we refer
  to it as an abstract data type, perhaps because it allows us to abstract
  a concept from the problem space into the solution space. In addition,
  the C++ compiler treats it like a new data type, and if you say a
  function expects a Stash, the compiler makes sure you pass a Stash to
  that function. So the same level of type checking happens with abstract
  data types (sometimes called user-defined types) as with built-in types.
  -->

  <para>
    La definición de <type>Stash</type> crea un nuevo tipo de dato. Se
    le pueden agregar nuevos elementos (<function>add()</function>),
    sacar (<function>fetch()</function>) y agrandarlo
    (<function>inflate()</function>). Se puede crear uno escribiendo
    <code>Stash s;</code> igual que cuando se crea un
    <type>float</type> diciendo <code>float x;</code>. Un
    <type>Stash</type> también tiene características y un
    comportamiento bien determinado. Aunque actúe igual que un tipo de
    dato predefinido como <type>float</type> se dice que
    <type>Stash</type> es un <emphasis>tipo abstracto de
    dato</emphasis> tal vez porque permite abstraer un concepto desde
    el espacio de los problemas al espacio de la solución. Además, el
    compilador de C++ lo tratará exactamente como a un nuevo tipo de
    dato y si, por ejemplo, declara una función que acepta un
    <type>Stash</type> como argumento, el compilador se asegurará de
    que no se le pase otra cosa a la función.  De modo que se realiza
    el mismo nivel de comprobación de tipos tanto para los tipos
    abstractos de datos (a veces también llamados <emphasis>tipos
    definidos por el usuario</emphasis>) como para los tipos
    predefinidos.
  </para>

  <!-- You can immediately see a difference, however, in the way you
  perform operations on objects. You say
  object.memberFunction(arglist). This is 'calling a member function
  for an object.' But in object-oriented parlance, this is also
  referred to as 'sending a message to an object.' So for a Stash s,
  the statement s.add(&i) 'sends a message to s' saying, 'add( ) this
  to yourself.' In fact, object-oriented programming can be summed up
  in a single phrase: sending messages to objects. Really, that's all
  you do ? create a bunch of objects and send messages to them. The
  trick, of course, is figuring out what your objects and messages
  are, but once you accomplish this the implementation in C++ is
  surprisingly straightforward.  -->
    <para>
      Sin embargo, notará inmediatamente una diferencia en la forma en
      que se realizan las operaciones sobre los objetos. Se hace
      <code>objeto.funciónMiembro(listaArgumentos)</code> o sea,
      <quote>se llama a un método de un objeto</quote>. Pero en la
      jerga de la orientación a objetos, eso también se denomina
      <quote>enviar un mensaje a un objeto</quote>. De modo que para
      una <varname>Stash s</varname>, en esta jerga la sentencia
      <code>s.add(&amp;i)</code> le <quote>envía un mensaje a
      <varname>s</varname></quote> diciéndole <quote>añadete
      (<function>add()</function>) esto</quote>. De hecho, la
      programación orientada a objetos se puede resumir en la
      siguiente frase: <emphasis>enviar mensajes a
      objetos</emphasis>. Realmente, ¿eso es todo lo que se hace?
      crear un montón de objetos y enviarles mensajes. El truco,
      obviamente, es entender qué <emphasis>son</emphasis> en nuestro
      problema los objetos y los mensajes, pero una vez que se ha
      cumplido esa etapa, la implementación en C++ será
      sorprendentemente directa.
    </para>
  </sect1>



<!-- Hasta aquí tradujo Sebastián Gurin -->


  <sect1>
    <!-- Object details -->
    <title>Detalles del objeto</title>

    <!--
    A question that often comes up in seminars is, "How big is an
    object, and what does it look like?" The answer is "about what you
    expect from a C struct." In fact, the code the C compiler produces
    for a C struct (with no C++ adornments) will usually look exactly
    the same as the code produced by a C++ compiler. This is reassuring
    to those C programmers who depend on the details of size and layout
    in their code, and for some reason directly access structure bytes
    instead of using identifiers (relying on a particular size and
    layout for a structure is a nonportable activity).
    -->

    <para>
      Una pregunta que surge a menudo en seminarios es <quote>¿Cómo de
      grande es un objeto y qué pinta tiene?</quote> La respuesta es
      <quote>más o menos lo que esperas de un <kw>struct</kw> en
      C</quote>. De hecho, el código que produce el compilador de C para
      un <kw>struct</kw> C (sin adornos C++) normalmente es
      <emphasis>exactamente</emphasis> el mismo que el producido por un
      compilador C++. Eso tranquiliza a aquellos programadores C que
      dependan de los detalles de tamaño y distribución de su código, y
      que por alguna razón accedan directamente a los bytes de la
      estructura en lugar de usar identificadores (confiar en un tamaño
      y distribución particular para una estructura no es portable).
    </para>


    <!--
    The size of a struct is the combined size of all of its
    members. Sometimes when the compiler lays out a struct, it adds
    extra bytes to make the boundaries come out neatly - this may
    increase execution efficiency. In Chapter 15, you'll see how in
    some cases "secret" pointers are added to the structure, but you
    don't need to worry about that right now.
    -->

    <para>
      El tamaño de una <kw>struct</kw> es la combinación de los
      tamaños de todos sus miembros. A veces cuando el compilador crea
      una <kw>struct</kw>, añade bytes extra para hacer que los
      límites encajen limpiamente - eso puede incrementar la
      eficiencia de la ejecución. En el <link linkend="C14">Capítulo
      14</link>, verá cómo en algunos casos se añaden punteros
      <quote>secretos</quote> a la estructura, pero no tiene que
      preocuparse de eso ahora.
    </para>

    <!--
    You can determine the size of a struct using the sizeof
    operator. Here's a small example:
    -->

    <para>
      Puede determinar el tamaño de una <kw>struct</kw> usando
      el operador <oper>sizeof</oper>. Aquí tiene un pequeño ejemplo:
    </para>


//: V1C04:Sizeof.cpp


    <!--
    On my machine (your results may vary) the first print statement
    produces 200 because each int occupies two bytes. struct B is
    something of an anomaly because it is a struct with no data
    members. In C, this is illegal, but in C++ we need the option of
    creating a struct whose sole task is to scope function names, so it
    is allowed. Still, the result produced by the second print statement
    is a somewhat surprising nonzero value. In early versions of the
    language, the size was zero, but an awkward situation arises when
    you create such objects: They have the same address as the object
    created directly after them, and so are not distinct. One of the
    fundamental rules of objects is that each object must have a unique
    address, so structures with no data members will always have some
    minimum nonzero size.
    -->

    <para>
      En mi máquina (los resultados pueden variar) el primer resultado
      produce 200 porque cada <type>int</type> ocupa 2 bytes. La
      <kw>struct</kw> <type>B</type> es algo anómalo porque es una
      <kw>struct</kw> sin atributos. En C, eso es ilegal, pero en C++
      necesitamos la posibilidad de crear una <kw>struct</kw> cuya
      única tarea es ofrecer un ámbito a nombres de funciones, por eso
      está permitido. Aún asi, el segundo resultado es un sorprendente
      valor distinto de cero. En versiones anteriores del lenguage, el
      tamaño era cero, pero aparecia una situación incómoda cuando se
      creaban estos objetos: tenían la misma dirección que el objeto
      creado antes que él, y eran indistinguibles. Una de las reglas
      fundamentales de los objetos es que cada objeto debe tener una
      dirección única, así que las estructuras sin atributos siempre
      tendrán tamaño mínimo distinto de cero.
    </para>

    <!--
    The last two sizeof statements show you that the size of the
    structure in C++ is the same as the size of the equivalent version
    in C. C++ tries not to add any unnecessary overhead.
    -->

    <para>
      Las dos últimas sentencias <oper>sizeof</oper> muestran que el
      tamaño de la estructura en C++ es el mismo que en la versión en
      C. C++ intenta no añadir ninguna sobrecarga innecesaria.
    </para>
  </sect1>


  <sect1>
    <title>Conveciones para los ficheros de cabecera</title>

    <!--
    When you create a struct containing member functions, you are
    creating a new data type. In general, you want this type to be
    easily accessible to yourself and others. In addition, you want to
    separate the interface (the declaration) from the implementation
    (the definition of the member functions) so the implementation can
    be changed without forcing a re-compile of the entire system. You
    achieve this end by putting the declaration for your new type in a
    header file.
    -->

    <para>
      Cuando se crea una <kw>struct</kw> que contiene
      funciones miembro, se está creando un nuevo tipo de dato. En
      general, se intenta que ese tipo sea fácilmente accesible. En
      resumen, se quiere que la interfaz (la declaración) esté separada
      de la implmentación (la definición de los métodos) de
      modo que la implementación pueda cambiar sin obligar a recompilar
      el sistema completo. Eso se consigue poniendo la declaración
      del nuevo tipo en un fichero de cabecera.
    </para>


    <!--
    When I first learned to program in C, the header file was a mystery
    to me. Many C books don't seem to emphasize it, and the compiler
    didn't enforce function declarations, so it seemed optional most of
    the time, except when structures were declared. In C++ the use of
    header files becomes crystal clear. They are virtually mandatory for
    easy program development, and you put very specific information in
    them: declarations. The header file tells the compiler what is
    available in your library. You can use the library even if you only
    possess the header file along with the object file or library file;
    you don't need the source code for the cpp file. The header file is
    where the interface specification is stored.
    -->

    <para>
      Cuando yo aprendí a programar en C, el fichero de cabecera era
      un misterio para mi. Muchos libros de C no hacen hincapié, y el
      compilador no obliga a hacer la declaración de las funciones,
      así que parecía algo opcional la mayor parte de las veces,
      excepto cuando se declaraban estrucutras. En C++ el uso de los
      ficheros de cabecera se vuelve claro como el cristal. Son
      prácticamente obligatorios para el desarrollo de programas
      sencillos, y en ellos podrá información muy específica:
      declaraciones. El fichero de cabecera informa al compilador de
      lo que hay disponible en la librería. Puede usar la librería
      incluso si sólo se dispone del fichero de cabecera y el fichero
      objeto o el fichero de librería; no necesita disponer del código
      fuente del fichero <filename>cpp</filename>. En el fichero de
      cabecera es donde se guarda la especificación de la interfaz.
    </para>

    <!--
    Although it is not enforced by the compiler, the best approach to
    building large projects in C is to use libraries; collect associated
    functions into the same object module or library, and use a header
    file to hold all the declarations for the functions. It is de
    rigueur in C++; you could throw any function into a C library, but
    the C++ abstract data type determines the functions that are
    associated by dint of their common access to the data in a
    struct. Any member function must be declared in the struct
    declaration; you cannot put it elsewhere. The use of function
    libraries was encouraged in C and institutionalized in C++.
    -->

    <para>
      Aunque el compilador no lo obliga, el mejor modo de construir
      grandes proyectos en C es usar librerías; colecciones de
      funciones asociadas en un mismo módulo objeto o librería, y usar
      un fichero de cabecera para colocar todas las declaraciones de
      las funciones. Es <emphasis>de rigor</emphasis> en C++, Podría
      meter cualquier función en una librería C, pero el tipo
      abstracto de dato C++ determina las funciones que están
      asociadas por medio del acceso común a los datos de una
      <kw>struct</kw>. Cualquier función miembro debe ser declarada en
      la declaración de la <kw>struct</kw>; no puede ponerse en otro
      lugar. El uso de librerías de funciones fue fomentado en C y
      institucionalizado en C++.
    </para>


    <sect2>
      <title>Importancia de los ficheros de cabecera</title>

      <!--
      When using a function from a library, C allows you the option of
      ignoring the header file and simply declaring the function by
      hand. In the past, people would sometimes do this to speed up the
      compiler just a bit by avoiding the task of opening and including
      the file (this is usually not an issue with modern compilers). For
      example, here's an extremely lazy declaration of the C function
      printf( ) (from %amp;stdio.h>):
      -->

      <para>
	Cuando se usa función de una librería, C le permite la
	posibilidad de ignorar el fichero de cabecera y simplemente
	declarar la función a mano. En el pasado, la gente hacía eso a
	veces para acelerar un poquito la compilación evitando la
	tarea de abrir e incluir el fichero (eso no supone ventaja
	alguna con los compiladores modernos). Por ejemplo, la
	siguiente es una declaración extremadamente vaga de la función
	<function>printf()</function> (de
	<filename>&lt;stdio.h></filename>):
      </para>

<programlisting>
printf(...);
</programlisting>

      <!--
      The ellipses specify a variable argument list[34], which says:
      printf( ) has some arguments, each of which has a type, but ignore
      that. Just take whatever arguments you see and accept them. By
      using this kind of declaration, you suspend all error checking on
      the arguments.
      -->

      <para>
	Estos puntos suspensivos <footnote><para>(N. de
	T. <emphasis>ellipsis</emphasis>) en inglés)</para>
	</footnote> especifican una <emphasis>lista de argumentos
	variable</emphasis>
	<footnote>
	  <!--
	  To write a function definition for a function that takes a
	  true variable argument list, you must use varargs, although
	  these should be avoided in C++. You can find details about the
	  use of varargs in your C manual.
	  -->
	  <para>
	    Para escribir una definición de función que toma una lista
	    de argumentos realmente variable, debe usar
	    <emphasis>varargs</emphasis>, aunque se debería evitar en
	    C++. Puede encontar información detallada sobre el uso de
	    <emphasis>varargs</emphasis> en un manual de C.
	  </para>
	</footnote>,

	que dice: la <function>printf()</function> tiene algunos
	argumentos, cada uno con su tipo, pero no se sabe
	cuales. Simplemente, coge los argumentos que veas y
	aceptalos. Usando este tipo de declaración, se suspenden todas
	las comprobaciones de errores en los argumentos.
      </para>

      <!--
      This practice can cause subtle problems. If you declare functions
      by hand, in one file you may make a mistake. Since the compiler
      sees only your hand-declaration in that file, it may be able to
      adapt to your mistake. The program will then link correctly, but
      the use of the function in that one file will be faulty. This is a
      tough error to find, and is easily avoided by using a header file.
      -->

      <para>
	Esta práctica puede causar problemas sutiles. Si declara
	funciones <quote>a mano</quote>, en un fichero puede cometer
	un error. Dado que el compilador sólo verá las declaraciones
	hechas a mano en ese fichero, se adaptará al error. El
	programa enlazará correctamente, pero el uso de la función en
	ese fichero será defectuoso. Se trata de un error difícil de
	encontrar, y que se puede evitar fácilmente usando el fichero
	de cabecera correspondiente.
      </para>

      <!--
      If you place all your function declarations in a header file, and
      include that header everywhere you use the function and where you
      define the function, you ensure a consistent declaration across
      the whole system. You also ensure that the declaration and the
      definition match by including the header in the definition file.
      -->

      <para>
	Si se colocan todas las declaraciones de funciones en un fichero
	de cabecera, y se incluye ese fichero allí donde se use la
	función se asegurará una declaración consistente a través del
	sistema completo. También se asegurará de que la declaración y
	la definición corresponden incluyendo el fichero de cabecera en
	el fichero de definición.
      </para>


      <!--
      If a struct is declared in a header file in C++, you must include
      the header file everywhere a struct is used and where struct
      member functions are defined. The C++ compiler will give an error
      message if you try to call a regular function, or to call or
      define a member function, without declaring it first. By enforcing
      the proper use of header files, the language ensures consistency
      in libraries, and reduces bugs by forcing the same interface to be
      used everywhere.
      -->

      <para>
	Si declara una <kw>struct</kw> en un fichero de cabecera en
	C++, <emphasis>debe</emphasis> incluir ese fichero allí donde
	se use una <kw>struct</kw> y también donde se definan los
	métodos de la <kw>struct</kw>. El compilador de C++ devolverá
	un mensaje de error si intenta llamar a una función, o llamar
	o definir un método, sin declararla primero. Imponiendo el uso
	apropiado de los ficheros de cabecera, el lenguaje asegura la
	consistencia de las librerías, y reduce el número de error
	forzando que se use la misma interface en todas partes.
      </para>


      <!--
      The header is a contract between you and the user of your
      library. The contract describes your data structures, and states
      the arguments and return values for the function calls. It says,
      "Here's what my library does." The user needs some of this
      information to develop the application and the compiler needs all
      of it to generate proper code. The user of the struct simply
      includes the header file, creates objects (instances) of that
      struct, and links in the object module or library (i.e.: the
      compiled code).
      -->

      <para>
	El fichero de cabecera es un contrato entre el programador de
	la librería y el que la usa. El contrato describe las
	estructuras de datos, expone los argumentos y valores de
	retorno para las funciones. Dice, <quote>Esto es lo que hace
	mi librería</quote>. El usuario necesita parte de esta
	información para desarrollar la aplicación, y el compilador
	necesita toda ella para generar el código correcto. El usuario
	de la <kw>struct</kw> simplemente incluye el fichero de
	cabecera, crea objetos (instancias) de esa <kw>struct</kw>, y
	enlaza con el módulo objeto o librería (es decir, el código
	compilado)
      </para>

      <!--
      The compiler enforces the contract by requiring you to declare all
      structures and functions before they are used and, in the case of
      member functions, before they are defined. Thus, you're forced to
      put the declarations in the header and to include the header in
      the file where the member functions are defined and the file(s)
      where they are used. Because a single header file describing your
      library is included throughout the system, the compiler can ensure
      consistency and prevent errors.
      -->

      <para>
	El compilador impone el contrato obligando a declarar todas
	las estruturas y funciones antes que puedan ser usadas y, en
	el caso de métodos, antes de ser definidos. De ese modo, se le
	obliga a poner las declaraciones en el fichero de cabecera e
	incluirlo en el fichero en el que se definen los métodos y en
	los ficheros en los que se usen. Como se incluye un único
	fichero que describe la librería para todo el sistema, el
	compilador puede asegurar la consistencia y evitar errores.
      </para>

      <!--
      There are certain issues that you must be aware of in order to
      organize your code properly and write effective header files. The
      first issue concerns what you can put into header files. The basic
      rule is "only declarations," that is, only information to the
      compiler but nothing that allocates storage by generating code or
      creating variables. This is because the header file will typically
      be included in several translation units in a project, and if
      storage for one identifier is allocated in more than one place,
      the linker will come up with a multiple definition error (this is
      C++'s one definition rule: You can declare things as many times
      as you want, but there can be only one actual definition for each
      thing).
      -->

      <para>
	Hay ciertos asuntos a los que debe prestar atención para
	organizar su código apropiadamente y escribir ficheros de
	cabecera eficaces. La regla básica es <quote>únicamente
	declaraciones</quote>, es decir, sólo información para el
	compiladore pero nada que requiera alojamiento en memoria ya
	sea generando código o creando variables. Esto es así porque
	el fichero de cabecera normalmente se incluye en varias
	unidades de traducción en un mismo proyecto, y si el
	almacenamiento para un identificador se pide en más de un
	sitio, el enlazador indicará un error de definición múltiple
	(ésta es la <emphasis>regla de definición única</emphasis> de
	C++: Se puede declarar tantas veces como se quiera, pero sólo
	puede haber una definición real para cada cosa).
      </para>

      <!--
      This rule isn't completely hard and fast. If you define a
      variable that is "file static" (has visibility only within a
      file) inside a header file, there will be multiple instances of
      that data across the project, but the linker won't have a
      collision[35]. Basically, you don't want to do anything in the
      header file that will cause an ambiguity at link time.
      -->

      <para>
	Esta norma no es completamente estricta. Si se define una
	variable que es <quote>file static</quote> (que tiene
	visibilidad sólo en un fichero) dentro de un fichero de
	cabecera, habrá múltiples instancias de ese dato a lo largo
	del proyecto, pero no causará un colisión en el enlazador
	<footnote>
	  <!--
	  However, in Standard C++ file static is a deprecated feature.
	  -->
	  <para>
	    Sin embargo, en C++ estándar <quote>file static</quote> es
	    una característica obsoleta.
	  </para>
	</footnote>. Básicamente, debe evitar cualquier cosa en los
	ficheros de cabecera que pueda causar una ambigüedad en tiempo
	de enlazado.
      </para>
    </sect2>


    <sect2>
      <title>El problema de la declaración múltiple</title>

      <!--
      The second header-file issue is this: when you put a struct
      declaration in a header file, it is possible for the file to be
      included more than once in a complicated program. Iostreams are a
      good example. Any time a struct does I/O it may include one of the
      iostream headers. If the cpp file you are working on uses more
      than one kind of struct (typically including a header file for
      each one), you run the risk of including the iostream> header
      more than once and re-declaring iostreams.
      -->


      <para>
	La segunda cuestión respecto a los ficheros de cabecera es ésta:
	cuando se pone una declaración de <kw>struct</kw> en
	un fichero de cabecera, es posible que el fichero sea incluido
	más de una vez en un programa complicado. Los iostreams son un
	buen ejemplo. Cada vez que una <kw>struct</kw> hace
	E/S debe incluir uno de los ficheros de cabecera iostream. Si el
	fichero <filename>cpp</filename> sobre el que se está trabajando
	utiliza más de un tipo de <kw>struct</kw> (típicamente
	incluyendo un fichero de cabecera para cada una), se está
	corriendo el riesgo de incluir el fichero
	<filename>&lt;isotream></filename> más de una vez y re-declarar
	los iostreams.
      </para>

      <!--
      The compiler considers the redeclaration of a structure (this
      includes both structs and classes) to be an error, since it would
      otherwise allow you to use the same name for different types. To
      prevent this error when multiple header files are included, you
      need to build some intelligence into your header files using the
      preprocessor (Standard C++ header files like iostream> already
      have this "intelligence").
      -->

      <para>
	El compilador considera que la redeclaración de una estructura
	(eso es aplicable tando a las <kw>struct</kw> como a las
	<kw>class</kw>) es un error, dado que de otro modo, debería
	permitir el uso del mismo nombre para tipos diferentes. Para
	evitar este error cuando se incluyen múltiples ficheros de
	cabecera, es necesario dar algo de inteligencia a los ficheros
	de cabecera usando el preprocesador (los ficheros de cabecera
	estándares como <filename>&lt;iostream></filename> también
	tienen esta <quote>inteligencia</quote>).
      </para>


      <!--
      Both C and C++ allow you to redeclare a function, as long as the
      two declarations match, but neither will allow the redeclaration
      of a structure. In C++ this rule is especially important because
      if the compiler allowed you to redeclare a structure and the two
      declarations differed, which one would it use?
      -->

      <para>
	Tanto C como C++ permiten redeclarar una función, siempre que
	las dos declaraciones coincidan, pero ni en ese caso se
	permite la redeclaración de una estructura. En C++ esta regla
	es especialmente importante porque si el compilador permitiera
	la redeclaración de una estructura y las dos declaraciones
	difirieran, ¿cuál debería usar?
      </para>

      <!--
      The problem of redeclaration comes up quite a bit in C++ because
      each data type (structure with functions) generally has its own
      header file, and you have to include one header in another if you
      want to create another data type that uses the first one.
      In any cpp file in your project, it's likely that you'll include several
      files that include the same header file. During a single
      compilation, the compiler can see the same header file several
      times. Unless you do something about it, the compiler will see the
      redeclaration of your structure and report a compile-time
      error. To solve the problem, you need to know a bit more about the
      preprocessor.  -->

      <para>
	El problema de la redeclaración se agrava un poco en C++ porque
	cada tipo de dato (estructura con funciones) generalmente tiene
	su propio fichero de cabecera, y hay que incluir un fichero de
	cabecera en otro si se quiere crear otro tipo de dato que use al
	primero. Es probable que en algún fichero
	<filename>cpp</filename> de su proyecto, que se incluyan varios
	ficheros que incluyan al mismo fichero de cabecera. Durante una
	compilación simple, el compilador puede ver el mismo fichero de
	cabecera varias veces. A menos que se haga algo al respecto, el
	compilador verá la redeclaración de la estructura e informará un
	error en tiempo de compilación. Para resolver el problema,
	necesitará saber un poco más acerca del preprocesador.
      </para>
    </sect2>


    <sect2>
      <title>
	Las directivas del preprocesador #define, #ifndef y #endif
      </title>

      <!--
      The preprocessor directive #define can be used to create
      compile-time flags. You have two choices: you can simply tell
      the preprocessor that the flag is defined, without specifying a
      value:
      -->

      <para>
	La directiva de preprocesador <kw>#define</kw> se
	puede usar para crear banderas en tiempo de compilación. Tiene
	dos opciones: puede simplemente indicar al preprocesador que la
	bandera está definida, sin especificar un valor:
      </para>

<programlisting>
    #define FLAG
</programlisting>

      <!--
      or you can give it a value (which is the typical C way to define
      a constant):
      -->

      <para>
	o puede darle un valor (que es la manera habitual en C para
	definir una constante):
      </para>

<programlisting>
    #define PI 3.14159
</programlisting>

      <!--
      In either case, the label can now be tested by the preprocessor
      to see if it has been defined:
      -->

      <para>
	En cualquier caso, ahora el preprocesador puede comprobar si la
	etiqueta ha sido definida:
      </para>

<programlisting>
    #ifdef FLAG
</programlisting>


      <!--
      This will yield a true result, and the code following the #ifdef
      will be included in the package sent to the compiler. This
      inclusion stops when the preprocessor encounters the statement
      -->

      <para>
	Esto producirá un resultado verdadero, y el código que sigue
	al <kw>#ifdef</kw> se incluirá en el paquete que se envía al
	compilador. Esta inclusión acaba cuando el preprocesador
	encuentra la sentencia:
      </para>

<programlisting>
    #endif
</programlisting>

      <!--
      or
      -->

      <para>
	o
      </para>

<programlisting>
    #endif // FLAG
</programlisting>

      <!--
      Any non-comment after the #endif on the same line is illegal,
      even though some compilers may accept it. The #ifdef/#endif
      pairs may be nested within each other.
      -->

      <para>
	Cualquier cosa después de <kw>#endif</kw> en la misma
	línea que no sea un comentario es ilegal, incluso aunque
	algunos compiladores lo acepten. Los pares
	<kw>#ifdef</kw>/<kw>#endif</kw> se pueden
	anidar.
      </para>

      <!--
      The complement of #define is #undef (short for "un-define"),
      which will make an #ifdef statement using the same variable
      yield a false result. #undef will also cause the preprocessor to
      stop using a macro. The complement of #ifdef is #ifndef, which
      will yield a true if the label has not been defined (this is the
      one we will use in header files).
      -->

      <para>
	El complementario de <kw>#define</kw> es <kw>#undef</kw>
	(abreviación de <quote>un-define</quote> que hará que una
	sentencia <kw>#ifdef</kw> que use la misma variable produzca
	un resultado falso. <kw>#undef</kw> también causará que el
	preprocesador deje de usar una macro. El complementario de
	<kw>#ifdef</kw> es <kw>#ifndef</kw>, que producirá verdadero
	si la etiqueta no ha sido definida (éste es el que usaremos en
	los ficheros de cabecera).
      </para>

      <!--
      There are other useful features in the C preprocessor. You
      should check your local documentation for the full set.
      -->

      <para>
	Hay otras características útiles en el preprocesador de
	C. Consulte la documentación de su preprocesador para ver todas
	ellas.
      </para>
    </sect2>


    <sect2>
      <title>Un estándar para los ficheros de cabecera</title>

      <!--
      In each header file that contains a structure, you should first
      check to see if this header has already been included in this
      particular cpp file. You do this by testing a preprocessor
      flag. If the flag isn't set, the file wasn't included and you
      should set the flag (so the structure can't get re-declared) and
      declare the structure. If the flag was set then that type has
      already been declared so you should just ignore the code that
      declares it. Here's how the header file should look:
      -->

      <para>
	En cada fichero de cabecera que contiene una estructura,
	primero debería comprobar si ese fichero ya ha sido includo en
	este fichero <filename>cpp</filename> particular. Hágalo
	comprobando una bandera del preprocesador. Si la bandera no
	está definida, el fichero no se ha incluido aún, y se debería
	definir la bandera (de modo que la estructura no se pueda
	redeclarar) y declarar la estructura. Si la bandera estaba
	definida entonces el tipo ya ha sido declarado de modo que
	debería ignorar el código que la declara. Así es como debería
	ser un fichero de cabecera:
      </para>

<programlisting>
    #ifndef HEADER_FLAG
    #define HEADER_FLAG
    // Escriba la declaración aquí...
    #endif // HEADER_FLAG
</programlisting>

    <!--
      As you can see, the first time the header file is included, the
      contents of the header file (including your type declaration) will
      be included by the preprocessor. All the subsequent times it is
      included - in a single compilation unit - the type declaration
      will be ignored. The name HEADER_FLAG can be any unique name, but
      a reliable standard to follow is to capitalize the name of the
      header file and replace periods with underscores (leading
      underscores, however, are reserved for system names). Here's an
      example:
    -->

      <para>
	Como puede ver, la primera vez que se incluye el fichero de
	cabecera, los contenidos del fichero (incluyendo la
	declaración del tipo) son incluidos por el preprocesador. Las
	demás veces que se incluya -en una única unidad de
	programación- la declaración del tipo será ignorada. El nombre
	<varname>HEADER_FLAG</varname> puede ser cualquier nombre
	único, pero un estándar fiable a seguir es poner el nombre del
	fichero de cabecera en mayúsculas y reemplazar los puntos por
	guiones bajos (sin embargo, el guión bajo al comienzo está
	reservado para nombres del sistema). Este es un ejemplo:
      </para>


//: V1C04:Simple.h


      <!--
      Although the SIMPLE_H after the #endif is commented out and thus
      ignored by the preprocessor, it is useful for documentation.
      -->

      <para>
	Aunque el <varname>SIMPLE_H</varname> después de
	<kw>#endif</kw> está comentado y es ignorado por el
	preprocesador, es útil para documentación.
      </para>

      <!--
      These preprocessor statements that prevent multiple inclusion are
      often referred to as include guards
      -->

      <para>
	Estas sentencias del preprocesador que impiden inclusiones
	múltiples se denominan a menudo <emphasis>guardas de
	inclusión</emphasis> (<emphasis>include guards</emphasis>)
      </para>
    </sect2>


    <sect2>
      <!-- Namespaces in headers -->
      <title>Espacios de nombres en los ficheros de cabecera</title>

      <!--
      You'll notice that using directives are present in nearly all the
      cpp files in this book, usually in the form:
      -->

      <para>
	Notará que las <emphasis>directivas using</emphasis> están
	presentes en casi todos los ficheros <filename>cpp</filename>
	de esto libro, normalmente en la forma:
      </para>

<programlisting>
    using namespace std;
</programlisting>

      <!--
      Since std is the namespace that surrounds the entire Standard C++
      library, this particular using directive allows the names in the
      Standard C++ library to be used without qualification. However,
      you'll virtually never see a using directive in a header file (at
      least, not outside of a scope). The reason is that the using
      directive eliminates the protection of that particular namespace,
      and the effect lasts until the end of the current compilation
      unit. If you put a using directive (outside of a scope) in a
      header file, it means that this loss of "namespace protection"
      will occur with any file that includes this header, which often
      means other header files. Thus, if you start putting using
      directives in header files, it's very easy to end up "turning
      off" namespaces practically everywhere, and thereby neutralizing
      the beneficial effects of namespaces.
      -->

      <para>
	Como <classname role="namespace">std</classname> es el espacio
	de nombres que encierra la librería Estándar C++ al completo,
	esta directiva <kw>using</kw> en particular permite
	que se puedan usar los nombres de la librería Estándar
	C++. Sin embargo, casi nunca verá una directiva
	<kw>using</kw> en un fichero de cabecera (al menos,
	no fuera de un bloque). La razón es que la directiva
	<kw>using</kw> elimina la protección de ese espacio
	de nombres en particular, y el efecto dura hasta que termina
	la unidad de compilación actual. Si pone una directiva
	<kw>using</kw> (fuera de un bloque) en un fichero de
	cabecera, significa que esta perdida de <quote>protección del
	espacio de nombres</quote> ocurrirá con cualquier fichero que
	incluya este fichero de cabecera, lo que a menudo significa
	otros ficheros de cabecera, es muy fácil acabar
	<quote>desactivando</quote> los espacios de nombres en todos
	sitios, y por tanto, neutralizando los efectos beneficiosos de
	los espacios de nombres.
      </para>

      <!--
      In short: don't put using directives in header files.
      -->

      <para>
	En resumen: no ponga directivas <kw>using</kw> en
	ficheros de cabecera.
      </para>

    </sect2>


    <sect2>
      <!-- Using headers in projects -->
      <title>Uso de los ficheros de cabecera en proyectos</title>

      <!--
      When building a project in C++, you'll usually create it by
      bringing together a lot of different types (data structures with
      associated functions). You'll usually put the declaration for
      each type or group of associated types in a separate header file,
      then define the functions for that type in a translation
      unit. When you use that type, you must include the header file to
      perform the declarations properly.
      -->

      <para>
	Cuando se construye un proyecto en C++, normalmente lo creará
	poniendo juntos un montón de tipos diferentes (estructuras de
	datos con funciones asociadas). Normalmente pondrá la
	declaración para cada tipo o grupo de tipos asociados en un
	fichero de cabecera separado, entonces definirá las funciones
	para ese tipo en una unidad de traducción. Cuando use ese tipo,
	deberá incluir el fichero de cabecera para efectuar las
	declaraciones apropiadamente.
      </para>


      <!--
      Sometimes that pattern will be followed in this book, but more
      often the examples will be very small, so everything - the
      structure declarations, function definitions, and the main( )
      function - may appear in a single file. However, keep in mind that
      you'll want to use separate files and header files in practice.
      -->

      <para>
	A veces ese patrón se seguirá en este libro, pero más a menudo
	los ejemplos serán muy pequeños, así que todo - la declaración
	de las estructuras, la definición de las funciones, y la función
	<function>main()</function> - pueden aparecer en un único
	fichero. Sin embargo, tenga presente que debería usar ficheros
	separados y ficheros de cabecera para aplicaciones reales.
      </para>

    </sect2>
  </sect1>


  <sect1>
    <title>Estructuras anidadas</title>

    <!--
    The convenience of taking data and function names out of the global
    name space extends to structures. You can nest a structure within
    another structure, and therefore keep associated elements
    together. The declaration syntax is what you would expect, as you
    can see in the following structure, which implements a push-down
    stack as a simple linked list so it "never" runs out of memory:
    -->

    <para>
      La conveniencia de coger nombres de funciones y datos fuera del
      espacio de nombre global es aplicable a las estructuras. Puede
      anidar una estructura dentro de otra estructura, y por tanto
      guardar juntos elementos asociados. La sintaxis de declaración
      es la que podría esperarse, tal como puede ver en la siguiente
      estructura, que implementa una pila como una lista enlazada
      simple de modo que <quote>nunca</quote> se queda sin memoria.
    </para>


//: V1C04:Stack.h


    <!--
    The nested struct is called Link, and it contains a pointer to the
    next Link in the list and a pointer to the data stored in the
    Link. If the next pointer is zero, it means you're at the end of
    the list.
    -->

    <para>
      La <kw>struck</kw> anidada se llama <type>Link</type>, y
      contiene un puntero al siguiente <type>Link</type> en la lista y
      un puntero al dato almacenado en el <type>Link</type>. Si el
      siguiente puntero es cero, significa que es el último elemento
      de la lista.
    </para>

    <!--
    Notice that the head pointer is defined right after the declaration
    for struct Link, instead of a separate definition Link* head. This
    is a syntax that came from C, but it emphasizes the importance of
    the semicolon after the structure declaration; the semicolon
    indicates the end of the comma-separated list of definitions of that
    structure type. (Usually the list is empty.)
    -->

    <para>
      Fíjese que el puntero <varname>head</varname> está definido a la
      derecha después de la declaración de la <kw>struct</kw>
      <type>Link</type>, es lugar de una definición separada
      <code>Link* head</code>. Se trata de una sintaxis que viene de
      C, pero que hace hincapié en la importancia del punto y coma
      después de la declaración de la estructura; el punto y coma
      indica el fin de una lista de definiciones separadas por comas
      de este tipo de estructura (Normalmente la lista está vacía.)
    </para>

    <!--
    The nested structure has its own initialize( ) function, like all
    the structures presented so far, to ensure proper
    initialization. Stack has both an initialize( ) and cleanup( )
    function, as well as push( ), which takes a pointer to the data you
    wish to store (it assumes this has been allocated on the heap), and
    pop( ), which returns the data pointer from the top of the Stack and
    removes the top element. (When you pop( ) an element, you are
    responsible for destroying the object pointed to by the data.) The
    peek( ) function also returns the data pointer from the top element,
    but it leaves the top element on the Stack.
    -->


    <!-- FIXME: los siguientes deberías ser "methodname" en lugar de
    "function" -->
    <para>
      La estructura anidada tiene su propia función
      <function>initialize()</function>, como todas las estructuras
      hasta el momento, para asegurar una inicialización
      adecuada. <classname>Stack</classname> tiene tanto función
      <function>initialice()</function> como
      <function>cleanup()</function>, además de
      <function>push()</function>, que toma un puntero a los datos que
      se desean almacenar (asume que ha sido alojado en el montículo),
      y <function>pop()</function>, que devuelve el puntero
      <varname>data</varname> de la cima de la
      <classname>Stack</classname> y elimina el elemento de la
      cima. (El que hace <function>pop()</function> de un elemento se
      convierte en responsable de la destrucción del objeto apuntado
      por <varname>data</varname>.) La función
      <function>peak()</function> también devuelve un puntero
      <varname>data</varname> a la cima de la pila, pero deja el
      elemento en la <classname>Stack</classname>.
    </para>

    <!--
    Here are the definitions for the member functions:
    -->

    <para>
      Aquí se muestran las definiciones de los métodos:
    </para>


//: V1C04:Stack.cpp


    <!--
    The first definition is particularly interesting because it shows
    you how to define a member of a nested structure. You simply use an
    additional level of scope resolution to specify the name of the
    enclosing struct. Stack::Link::initialize( ) takes the arguments and
    assigns them to its members.
    -->

    <para>
      La primera definición es particularmente interesante porque
      muestra cómo se define un miembro de una estructura
      anidada. Simplemente se usa un nivel adicional de resolución de
      ámbito para especificar el nombre de la <kw>struct</kw>
      interna. <methodname>Stack::Link::initialize()</methodname> toma
      dos argumentos y los asigna a sus atributos.
    </para>


    <!--
    Stack::initialize( ) sets head to zero, so the object knows it
    has an empty list.
    -->

    <para>
      <methodname>Stack::initialize()</methodname> asgina cero a
      <varname>head</varname>, de modo que el objeto sabe que
      tiene una lista vacía.
    </para>


    <!--
    Stack::push( ) takes the argument, which is a pointer to the
    variable you want to keep track of, and pushes it on the
    Stack. First, it uses new to allocate storage for the Link it will
    insert at the top. Then it calls Link's initialize( ) function to
    assign the appropriate values to the members of the Link. Notice
    that the next pointer is assigned to the current head; then head is
    assigned to the new Link pointer. This effectively pushes the Link
    in at the top of the list.
    -->

    <para>
      <methodname>Stack::push()</methodname> toma el argumento, que es
      un puntero a la variable a la que se quiere seguir la pista, y la
      apila en la <classname>Stack</classname>. Primero, usa
      <kw>new</kw> para pedir alojamiento para el
      <classname>Link</classname> que se insertará en la cima. Entonces
      llama a la función <methodname>initialize()</methodname> para
      asignar los valores apropiados a los miembres del
      <classname>Link</classname>. Fijese que el siguiente puntero se
      asigna al <varname>head</varname> actual; entonces
      <varname>head</varname> se asigna al nuevo puntero
      <classname>Link</classname>. Esto apila eficazmente el
      <classname>Link</classname> en la cima de la lista.
    </para>


    <!--
    Stack::pop( ) captures the data pointer at the current top of the
    Stack; then it moves the head pointer down and deletes the old top
    of the Stack, finally returning the captured pointer. When pop( )
    removes the last element, then head again becomes zero, meaning the
    Stack is empty.
    -->

    <para>
      <methodname>Stack::pop()</methodname> captura el puntero
      <varname>data</varname> en la cima actual de la
      <classname>Stack</classname>; entonces mueve el puntero
      <varname>head</varname> hacia abajo y borra la anterior cima de
      la <classname>Stack</classname>, finalmente devuelve el puntero
      capturado. Cuando <methodname>pop()</methodname> elemina el último
      elemento, <varname>head</varname> vuelve a ser cero, indicando que
      la <classname>Stack</classname> está vacía.
    </para>


    <!--
    Stack::cleanup( ) doesn't actually do any cleanup. Instead, it
    establishes a firm policy that "you (the client programmer using
    this Stack object) are responsible for popping all the elements off
    this Stack and deleting them." The require( ) is used to indicate
    that a programming error has occurred if the Stack is not empty.
    -->

    <para>
      <methodname>Stack::cleanup()</methodname> realmente no hace
      ninguna limpieza. En su lugar, establece una política firme que
      dice <quote>el programador cliente que use este objeto
      <classname>Stack</classname> es responsable de des-apilar todos
      los elementos y borrarlos</quote>. <function>require()</function>
      se usa para indicar que ha ocurrido un error de programación si la
      <classname>Stack</classname> no está vacía.
    </para>


    <!--
    Why couldn't the Stack destructor be responsible for all the
    objects that the client programmer didn't pop( )? The problem is
    that the Stack is holding void pointers, and you'll learn in
    Chapter 13 that calling delete for a void* doesn't clean things up
    properly. The subject of "who's responsible for the memory" is
    not even that simple, as we'll see in later chapters.
    -->

    <para>
      ¿Por qué no puede el destructor de <classname>Stack</classname>
      responsabilizarse de todos los objetos que el programador
      cliente no des-apiló? El problema es que la
      <classname>Stack</classname> está usando punteros
      <type>void</type>, y tal como se verá en el <link
      linkend="C13">Capítulo 13</link> usar <kw>delete</kw> para un
      <type>void*</type> no libera correctamente. El asunto de
      <quote>quién es el responsable de la memoria</quote> no siempre
      es sencillo, tal como veremos en próximos capítulos.
    </para>



    <!--
    Here's an example to test the Stack:
    -->

    <para>
      Un ejemplo para probar la <classname>Stack</classname>:
    </para>


//: V1C04:StackTest.cpp


    <!--
    This is similar to the earlier example, but it pushes lines from a
    file (as string pointers) on the Stack and then pops them off, which
    results in the file being printed out in reverse order. Note that
    the pop( ) member function returns a void* and this must be cast
    back to a string* before it can be used. To print the string, the
    pointer is dereferenced.
    -->

    <para>
      Es similar al ejemplo anterior, pero en este se apilan líneas
      de un fichero (como punteros a cadena) en la
      <classname>Stack</classname> y después los des-apila, lo que
      provoca que el fichero sea imprimido en orden inverso. Fíjese que
      <methodname>pop()</methodname> devuelve un <type>void*</type>
      que debe ser moldeado a <type>string*</type> antes de poderse
      usar. Para imprimir una cadena, el puntero es dereferenciado.
    </para>


    <!--
    As textlines is being filled, the contents of line is "cloned" for
    each push( ) by making a new string(line). The value returned from
    the new-expression is a pointer to the new string that was created
    and that copied the information from line. If you had simply passed
    the address of line to push( ), you would end up with a Stack filled
    with identical addresses, all pointing to line. You'll learn more
    about this "cloning" process later in the book.
    -->

    <para>
      Como <varname>textlines</varname> se llena, el contenido de
      <varname>line</varname> se <quote>clona</quote> para cada
      <methodname>push()</methodname> creando un <code>new
      string(line)</code>. El valor devuelto por la expresión
      <kw>new</kw> es un puntero al nuevo <type>string</type> que fue
      creado y al que se ha copiado la información de la
      <varname>line</varname>. Si se hubiera pasado directamente la
      dirección de <varname>line</varname> a
      <methodname>push()</methodname>, la <classname>Stack</classname>
      se llenaría con direcciones idénticas, todas apuntando a
      <varname>line</varname>. Más adelante en ese libro aprenderá más
      sobre este proceso de <quote>clonación</quote>.
    </para>


    <!--
    The file name is taken from the command line. To guarantee that
    there are enough arguments on the command line, you see a second
    function used from the require.h header file: requireArgs( ), which
    compares argc to the desired number of arguments and prints an
    appropriate error message and exits the program if there aren't
    enough arguments.
    -->

    <para>
      El nombre del fichero se toma de línea de comando. Para garantizar
      que hay suficientes argumentos en la línea de comando, se usa una
      segunda función del fichero de cabecera
      <filename>require.h</filename>: <function>requireArgs()</function>
      que compara <varname>argc</varname> con el número de argumentos
      deseado e imprime un mensaje de error y termina el programa si no
      hay suficientes argumentos.
    </para>


    <sect2>
      <title>Resolución de ámbito global</title>

    <!--
      The scope resolution operator gets you out of situations in which
      the name the compiler chooses by default (the "nearest" name)
      isn't what you want. For example, suppose you have a structure
      with a local identifier a, and you want to select a global
      identifier a from inside a member function. The compiler would
      default to choosing the local one, so you must tell it to do
      otherwise. When you want to specify a global name using scope
      resolution, you use the operator with nothing in front of it. Here'
      s an example that shows global scope resolution for both a
      variable and a function:
    -->

      <para>
	El operador de resolución de ámbito puede ayudar en situaciones
	en las que el nombre elegido por el compilador (el nombre
	<quote>más cercano</quote>) no es el que se quiere. Por ejemplo,
	suponga que tiene una estructura con un identificador local
	<varname>a</varname>, y quiere seleccionar un identificador
	global <varname>a</varname> desde dentro de un método. El
	compilador, por defecto, elegirá el local, de modo que es
	necesario decirle que haga otra cosa. Cuando se quiere
	especificar un nombre global usando la resolución de ámbito,
	debe usar el operador sin poner nada delante de él. A
	continuación aparece un ejemplo que muestra la resolución de
	ámbito global tanto para una variable como para una función:
      </para>


//: V1C04:Scoperes.cpp


      <!--
      Without scope resolution in S::f( ), the compiler would default to
      selecting the member versions of f( ) and a
      -->

      <para>
	Sin resolución de ámbito en <methodname>S::f()</methodname>, el
	compilador elegiría por defecto las versiones miembro para
	<function>f()</function> y <varname>a</varname>.
      </para>
    </sect2>
  </sect1>


  <sect1>
    <title>Resumen</title>

    <!--
    In this chapter, you've learned the fundamental "twist" of C++:
    that you can place functions inside of structures. This new type of
    structure is called an abstract data type, and variables you create
    using this structure are called objects, or instances, of that
    type. Calling a member function for an object is called sending a
    message to that object. The primary action in object-oriented
    programming is sending messages to objects.
    -->

    <para>
      En este capítulo, ha aprendido lo fundamental de C++: que puede
      poner funciones dentro de las estructuras. Este nuevo tipo de
      estructura se llama <emphasis>tipo abstracto de dato</emphasis>,
      y las variables que se crean usando esta estructura se llaman
      <emphasis>objetos</emphasis>, o <emphasis>instancias</emphasis>,
      de ese tipo. Invocar un método de una objeto se denomina
      <emphasis>enviar un mensaje</emphasis> al objeto. La actividad
      principal en la programación orientada a objetos es el envío de
      mensajes a objetos.
    </para>


    <!--
    Although packaging data and functions together is a significant
    benefit for code organization and makes library use easier because
    it prevents name clashes by hiding the names, there's a lot more
    you can do to make programming safer in C++. In the next chapter,
    you'll learn how to protect some members of a struct so that only
    you can manipulate them. This establishes a clear boundary between
    what the user of the structure can change and what only the
    programmer may change.
    -->

    <para>
      Aunque empaquetar datos y funciones juntos es un benificio
      significativo para la organización del código y hace la librería
      sea más fácil de usar porque previene conflictos de nombres
      ocultando los nombres, hay mucho más que se puede hacer para
      tener programación más segura en C++. En el próximo capítulo,
      aprenderá cómo proteger algunos miembros de una <kw>struct</kw>
      para que sólo el programador pueda manipularlos. Esto establece
      un límite claro entre lo que puede cambiar el usuario de la
      estructura y lo que sólo el programador puede cambiar.
    </para>
  </sect1>


  <sect1>
    <title>Ejercicios</title>

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

    <orderedlist>
      <listitem>
	<!--
	1. In the Standard C library, the function puts( ) prints a char
	array to the console (so you can say puts("hello")). Write a C
	program that uses puts( ) but does not include &lt;stdio.h> or
	otherwise declare the function. Compile this program with your C
	compiler. (Some C++ compilers are not distinct from their C
	compilers; in this case you may need to discover a command-line
	flag that forces a C compilation.) Now compile it with the C++
	compiler and note the difference.
	-->
	<para>
	  En la librería C estándar, la función
	  <function>puts()</function> imprime un array de caracteres a
	  la consola (de modo que puede escribir
	  <code>puts("Hola")</code>). Escriba un program C que use
	  <function>puts()</function> pero que no incluya
	  <filename>&lt;stdio.h></filename> o de lo contrario declare
	  la función. Compile ese programa con su compilador de
	  C. (algunos compiladores de C++ no son programas distintos
	  de sus compiladores de C, es ese caso puede que necesite
	  averiguar que opción de línea de comando fuerza una
	  compilación C.)  Ahora compílelo con el compilador C++ y
	  preste atención a la diferencia.
	</para>
      </listitem>
      <listitem>
	<!--
	2. Create a struct declaration with a single member function, then
	create a definition for that member function. Create an object of
	your new data type, and call the member function.
	-->
	<para>
	  Cree una declaración de <kw>struct</kw> con un único
	  método, entonces cree una definición para ese método. Cree un
	  objeto de su nuevo tipo de dato, e invoque el método.
	</para>
      </listitem>
      <listitem>
	<!--
	3. Change your solution to Exercise 2 so the struct is declared in a
	properly "guarded" header file, with the definition in one cpp
	file and your main( ) in another.
	-->
	<para>
	  Cambie su solución al Ejercicio 2 para que la
	  <kw>struct</kw> sea declarada en un fichero de
	  cabecera convenientemente <quote>guardado</quote>, con la
	  definición en un fichero <filename>cpp</filename> y el
	  <function>main()</function> en otro.
	</para>
      </listitem>
      <listitem>
	<!--
	4. Create a struct with a single int data member, and two global
	functions, each of which takes a pointer to that struct. The
	first function has a second int argument and sets the struct's
	int to the argument value, the second displays the int from the
	struct. Test the functions.
	-->
	<para>
	  Cree una <kw>struct</kw> con un único atributo de
	  tipo entero, y dos funciones globales, cada una de las cuales
	  acepta un puntero a ese <kw>struct</kw>. La primera
	  función tiene un segundo argumento de tipo entero y asigna
	  al entero de l  <kw>struct</kw> el valor del
	  argumento, la segunda muestra el entero de la
	  <kw>struct</kw>. Prueba las funciones.
	</para>
      </listitem>
      <listitem>
	<!--
	5. Repeat Exercise 4 but move the functions so they are member
	functions of the struct, and test again.
	-->
	<para>
	  Repita el Ejercicio 4 pero mueva las función de modo que sean
	  métodos de la <kw>struct</kw>, y pruebe de nuevo.
	</para>
      </listitem>
      <listitem>
	<!--
	6. Create a class that (redundantly) performs data member selection
	and a member function call using the this keyword (which refers
	to the address of the current object).
	-->
	<para>
	  Cree una clase que (de forma redundante) efectúe la
	  selección de atributos y una llamada a método usando la
	  palabra reservada <kw>this</kw> (que indica a la dirección
	  del objeto actual)
	</para>
      </listitem>
      <listitem>
	<!--
	7. Make a Stash that holds doubles. Fill it with 25 double values,
	then print them out to the console.
	-->
	<para>
	  Cree una <classname>Stach</classname> que mantenga
	  <type>doubles</type>. Rellénela con 25 valores
	  <type>double</type>, después muéstrelos en consola.
	</para>
      </listitem>
      <listitem>
	<!--
	8. Repeat Exercise 7 with Stack.
	-->
	<para>
	  Repita el Ejercicio 7 con <classname>Stack</classname>.
	</para>
      </listitem>
      <listitem>
	<!--
	9. Create a file containing a function f( ) that takes an int
	argument and prints it to the console using the printf( )
	function in &lt;stdio.h> by saying: printf("%d\n", i) in which i
	is the int you wish to print. Create a separate file containing
	main( ), and in this file declare f( ) to take a float
	argument. Call f( ) from inside main( ). Try to compile and link
	your program with the C++ compiler and see what happens. Now
	compile and link the program using the C compiler, and see what
	happens when it runs. Explain the behavior.
	-->
	<para>
	  Cree un fichero que contenga una función
	  <function>f()</function> que acepte un argumento entero y lo
	  imprima en consola usando la función
	  <function>printf()</function> de
	  <filename>&lt;stdio></filename> escribiendo:
	  <code>printf("%d\n", i)</code> donde <varname>i</varname> es
	  el entero que desea imprimir. Cree un fichero separado que
	  contenga <function>main()</function>, y este fichero declare
	  <function>f()</function> pero aceptando un argumento
	  <type>float</type>. Invoque <function>f()</function> desde
	  <function>main()</function>. Intente compilar y enlazar el
	  programa con el compilador C++ y vea qué ocurre. Ahora
	  compile y enlace el programa usando el compilador C, y vea
	  que ocurre cuando se ejecuta. Explique el comportamiento.
	</para>
      </listitem>
      <listitem>
	<!--
	10. Find out how to produce assembly language from your C and C++
        compilers. Write a function in C and a struct with a single
        member function in C++. Produce assembly language from each and
        find the function names that are produced by your C function and
        your C++ member function, so you can see what sort of name
        decoration occurs inside the compiler.
	-->
	<para>
	  Averigüe cómo generar lenguaje ensamblador con su compilador C
	  y C++. Escriba una función en C y una
	  <kw>struct</kw> con un único miembro en C++. Genere
	  la salida en lenguaje ensamblador para cada una de ellas y
	  encuentre los nombres de ambas funciones, de modo que pueda
	  ver qué tipo de <quote>decoración</quote> aplica el compilador
	  a dichos nombres.
	</para>
      </listitem>
      <listitem>
	<!--
	11. Write a program with conditionally-compiled code in main( ), so
        that when a preprocessor value is defined one message is
        printed, but when it is not defined another message is
        printed. Compile this code experimenting with a #define within
        the program, then discover the way your compiler takes
        preprocessor definitions on the command line and experiment with
        that.
	-->
	<para>
	  Escriba un programa con código condicionalmente-compilado en
	  <function>main()</function>, para que cuando se defina un
	  valor del preprocesador, se muestre un mensaje, pero cuando no
	  se defina, se imprima otra mensaje distinto. Compile este
	  experimentando con un <kw>#define</kw> en el
	  programa, después averigüe la forma de indicar al compilador
	  definiciones de preprocesador en la línea de comandos y
	  experimente con ello.
	</para>
      </listitem>
      <listitem>
	<!--
	12. Write a program that uses assert( ) with an argument that is
        always false (zero) to see what happens when you run it. Now
        compile it with #define NDEBUG and run it again to see the
        difference.
	-->
	<para>
	  Escriba un programa que use <function>assert()</function> con
	  un argumento que siempre sea falso (cero) y vea que ocurre
	  cuando lo ejecuta. Ahora compílelo con <code>#define
	  NDEBUG</code> y ejecútelo de nuevo para ver la
	  diferencia.
	</para>
      </listitem>
      <listitem>
	<!--
	13. Create an abstract data type that represents a videotape in a
        video rental store. Try to consider all the data and operations
        that may be necessary for the Video type to work well within the
        video rental management system. Include a print( ) member
        function that displays information about the Video.
	-->
	<para>
	  Cree un tipo abstracto de dato que represente un cinta de
	  vídeo en una tienda de alquiler. Considere todos los datos y
	  operaciones que serían necesarias para que el tipo
	  <classname>Video</classname> funcione con el sistema de
	  gestión de la tienda. Incluya un método
	  <methodname>print()</methodname> que muestre información sobre
	  el <classname>Video</classname>
	</para>
      </listitem>
      <listitem>
	<!--
	14. Create a Stack object to hold the Video objects from Exercise
        13. Create several Video objects, store them in the Stack, then
        display them using Video::print( ).
	-->
	<para>
	  Cree un objeto <classname>Pila</classname> que almacene
	  objetos <classname>Video</classname> del Ejercicio 13. Cree
	  varios objetos <classname>Video</classname>, guárdelos en la
	  <classname>Stack</classname> y entonces muéstrelos usando
	  <methodname>Video::print()</methodname>.
	</para>
      </listitem>
      <listitem>
	<!--
	15. Write a program that prints out all the sizes for the
        fundamental data types on your computer using sizeof.
	-->
	<para>
	  Escriba un programa que muestre todos los tamaños de los tipos
	  de datos fundamentales de su computadora usando
	  <oper>sizeof</oper>.
	</para>
      </listitem>
      <listitem>
	<!--
	16. Modify Stash to use a vector&lt;char> as its underlying data
        structure.
	-->
	<para>
	  Modifique <classname>Stash</classname> para usar
	  <code>vector&lt;char></code> como
	  estructura de datos subyacente.
	</para>
      </listitem>
      <listitem>
	<!--
	17. Dynamically create pieces of storage of the following types,
        using new: int, long, an array of 100 chars, an array of 100
        floats. Print the addresses of these and then free the storage
        using delete.
	-->
	<para>
	  Cree dinámicamente espacio de almacenamiento para los
	  siguiente tipos usando <kw>new</kw>:
	  <type>int</type>, <type>long</type>, un array de 100
	  <type>char</type>, un array de 100 <type>float</type>. Muestre
	  sus direcciones y libérelos usando <kw>delete</kw>.
	</para>
      </listitem>
      <listitem>
	<!--
	18. Write a function that takes a char* argument. Using new,
        dynamically allocate an array of char that is the size of the
        char array that's passed to the function. Using array indexing,
        copy the characters from the argument to the dynamically
        allocated array (don't forget the null terminator) and return
        the pointer to the copy. In your main( ), test the function by
        passing a static quoted character array, then take the result of
        that and pass it back into the function. Print both strings and
        both pointers so you can see they are different storage. Using
        delete, clean up all the dynamic storage.
	-->
	<para>
	  Escriba una función que tome un argumento
	  <type>char*</type>. Usando <kw>new</kw>, pida
	  alojamiento dinámico para un array de <type>char</type> con un
	  tamaño igual al argumento pasado a la función. Usando
	  indexación de array, copie los caracteres del argumento al
	  array dinámico (no olvide el terminador nulo) y devuelva el
	  puntero a la copia. En su <function>main()</function>, pruebe
	  la función pasando una cadena estática entre comillas, después
	  tome el resultado y páselo de nuevo a la función. Muestre
	  ambas cadenas y punteros para poder ver que tienen distinta
	  ubicación. Mediante <kw>delete</kw> libere todo el
	  almacenamiento dinámico.
	</para>
      </listitem>
      <listitem>
	<!--
	19. Show an example of a structure declared within another structure
        (a nested structure). Declare data members in both structs, and
        declare and define member functions in both structs. Write a
        main( ) that tests your new types.
	-->
	<para>
	  Haga un ejemplo de estructura declarada con otra estructura
	  dentro (un estructura anidada). Declare atributos en ambas
	  <kw>structs</kw>, y declare y defina métodos en
	  ambas <kw>structs</kw>. Escriba un
	  <function>main()</function> que pruebe los nuevos tipos.
	</para>
      </listitem>
      <listitem>
	<!--
	20. How big is a structure? Write a piece of code that prints the
        size of various structures. Create structures that have data
        members only and ones that have data members and function
        members. Then create a structure that has no members at
        all. Print out the sizes of all these. Explain the reason for
        the result of the structure with no data members at all.
	-->
	<para>
	  ¿Cómo de grande es una estructura? Escriba un trozo de código
	  que muestre el tamaño de varias estructuras. Cree estructuras
	  que tengan sólo atributos y otras que tengan atributos y
	  métodos. Después cree una estructura que no tenga ningún
	  miembro. Muestre los tamaños de todas ellas. Explique el
	  motivo del tamaño de la estructura que no tiene ningún
	  miembro.
	</para>
      </listitem>
      <listitem>
	<!--
	21. C++ automatically creates the equivalent of a typedef for
        structs, as you've seen in this chapter. It also does this for
        enumerations and unions. Write a small program that demonstrates
        this.
	-->
	<para>
	  C++ crea automáticamente el equivalente de <kw>typedef</kw>
	  para <kw>structs</kw>, tal como ha visto en este
	  capítulo. También lo hace para las enumeraciones y las
	  uniones. Escriba un pequeño programa que lo demuestre.
	</para>
      </listitem>
      <listitem>
	<!--
	22. Create a Stack that holds Stashes. Each Stash will hold five
        lines from an input file. Create the Stashes using new. Read a
        file into your Stack, then reprint it in its original form by
        extracting it from the Stack.
	-->
	<para>
	  Cree una <classname>Stack</classname> que maneje
	  <classname>Stash</classname>es. Cada
	  <classname>Stash</classname> mantendrá cinco líneas
	  procedentes de un fichero. Cree las
	  <classname>Stash</classname> usando
	  <kw>new</kw>. Lea un fichero en su
	  <classname>Stack</classname>, después muéstrelo en su forma
	  original extrayéndolo de la <classname>Stack</classname>.
	</para>
      </listitem>
      <listitem>
	<!--
	23. Modify Exercise 22 so that you create a struct that encapsulates
        the Stack of Stashes. The user should only add and get lines via
        member functions, but under the covers the struct happens to use
        a Stack of Stashes.
	-->
	<para>
	  Modifique el Ejercicio 22 de modo que cree una estructura que
	  encapsule la <classname>Stack</classname> y las
	  <classname>Stash</classname>. El usuario sólo debería añadir y
	  pedir líneas a través de sus métodos, pero debajo de la
	  cubierta la estructura usa una
	  <classname>Stack</classname>(pila) de
	  <classname>Stash</classname>es.
	</para>
      </listitem>
      <listitem>
	<!--
	24. Create a struct that holds an int and a pointer to another
        instance of the same struct. Write a function that takes the
        address of one of these structs and an int indicating the length
        of the list you want created. This function will make a whole
        chain of these structs (a linked list), starting from the
        argument (the head of the list), with each one pointing to the
        next. Make the new structs using new, and put the count (which
        object number this is) in the int. In the last struct in the
        list, put a zero value in the pointer to indicate that it's the
        end. Write a second function that takes the head of your list
        and moves through to the end, printing out both the pointer
        value and the int value for each one.
	-->
	<para>
	  Cree una <kw>struct</kw> que mantenga un
	  <type>int</type> y un puntero a otra instancia de la misma
	  <kw>struct</kw>. Escriba una función que acepte como
	  parámetro la dirección de una de estas
	  <kw>struct</kw> y un <type>int</type> indicando la
	  longitud de la lista que se desea crear. Esta función creará
	  una cadena completa de estas <kw>struct</kw> (una
	  lista enlazada), empezando por el argumento (la cabeza de la
	  lista), con cada una apuntando a la siguiente. Cree las nuevas
	  <kw>struct</kw> usando <kw>new</kw>, y
	  ponga la posición (que número de objeto es) en el
	  <type>int</type>. En la última <kw>struct</kw> de la
	  lista, ponga un valor cero en el puntero para indicar que es
	  el último. Escriba una segunda función que acepte la cabeza de
	  la lista y la recorra hasta el final, mostrando los valores
	  del puntero y del <type>int</type> para cada una.
	</para>
      </listitem>
      <listitem>
	<!--
	25. Repeat Exercise 24, but put the functions inside a struct
        instead of using "raw" structs and functions.
	-->
	<para>
	  Repita el ejercicio 24, pero poniendo las funciones dentro de
	  una <kw>struct</kw> en lugar de usar <kw>struct</kw> y
	  funciones <quote>crudas</quote>.
	</para>
      </listitem>
    </orderedlist>
  </sect1>
</chapter>