PensarEnC++ / V1-C08.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
<?xml  version="1.0" encoding="utf-8"?>
<!-- -*- sgml -*- -->
<!--
  Editor:              Emacs 21/PSGML
  Traducción original: David Villa <dvilla@gmx.net>
  Formateado DocBook:  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="C08">

  <title>Constantes</title>

  <!-- [PAG:353] -->
  <!--
  The concept of constant (expressed by the const keyword) was created
  to allow the programmer to draw a line between what changes and what
  doesn't. This provides safety and control in a C++ programming
  project.
  -->
  <highlights>
    <para>
      El concepto de constante (expresión con la palabra reservada
      <kw>const</kw>) se creó para permitir a los programadores marcar
      la diferencia entre lo que puede cambiar y lo que no. Esto
      facilita el control y la seguridad en un proyecto de
      programación.
    </para>
  </highlights>

  <!-- [PAG: 354] -->
  <!--
  Since its origin, const has taken on a number of different
  purposes. In the meantime it trickled back into the C language where
  its meaning was changed. All this can seem a bit confusing at first,
  and in this chapter you'll learn when, why, and how to use the const
  keyword. At the end there's a discussion of volatile, which is a near
  cousin to const (because they both concern change) and has identical
  syntax.
  -->
  <para>
    Desde su origen, <kw>const</kw> ha sido utilizada para diferentes
    propósitos. Mientras tanto FIXME:it trickled back en el lenguaje C
    en el que su significado cambió. Todo esto puede parecer un poco
    confuso al principio, y en este capítulo aprenderá cuándo, porqué
    y cómo usar la palabra reservada <kw>const</kw>. Hacia el final se
    expone una disertación sobre <emphasis>volatile</emphasis>, que es
    familia de <kw>const</kw> (ambos se refieren a los cambios) y su
    sintaxis es idéntica.
  </para>

  <!--
  The first motivation for const seems to have been to eliminate the use
  of preprocessor #defines for value substitution. It has since been put
  to use for pointers, function arguments, return types, class objects
  and member functions. All of these have slightly different but
  conceptually compatible meanings and will be looked at in separate
  sections in this chapter.
  -->
  <para>
    El primer motivo para la creación de <kw>const</kw> parece que fue
    eliminar el uso de la directiva del preprocesador <kw>#define</kw>
    para sustitución de valores. Desde entonces se usa para punteros,
    argumentos de funciones, tipos de retorno, objetos y funciones
    miembro. Todos ellos tienen pequeñas diferencias pero su
    significado es conceptualmente compatible. Se tratarán en las siguientes
    secciones de este capítulo.
  </para>

  <sect1>
    <!-- : Value substitution -->
    <title>Sustitución de valores</title>

    <!--
    When programming in C, the preprocessor is liberally used to create
    macros and to substitute values. Because the preprocessor simply does
    text replacement and has no concept nor facility for type checking,
    preprocessor value substitution introduces subtle problems that can be
    avoided in C++ by using const values.
    -->
    <para>
      Cuando se programa en C, se usa libremente el preprocesador para
      crear macros y sustituir valores. El preprocesador simplemente
      hace un reemplazo textual y no realiza ninguna comprobación de
      tipo. Por ello, la sustitución de valores introduce pequeños
      problemas que se pueden evitar usando valores constantes.
    </para>

    <!--
    The typical use of the preprocessor to substitute values for names in
    C looks like this:
    -->
    <para>
      El uso más frecuente del preprocesador es la sustitución de
      valores por nombres, en C es algo como:
    </para>


<programlisting>
#define BUFSIZE 100
</programlisting>

    <!--
    BUFSIZE is a name that only exists during preprocessing, therefore it
    doesn't occupy storage and can be placed in a header file to provide a
    single value for all translation units that use it. It's very
    important for code maintenance to use value substitution instead of
    so-called "magic numbers." If you use magic numbers in your code,
    not only does the reader have no idea where the numbers come from or
    what they represent, but if you decide to change a value, you must
    perform hand editing, and you have no trail to follow to ensure you
    don't miss one of your values (or accidentally change one you
    shouldn't).
    -->
    <para>
      <varname>BUFSIZE</varname> es un nombre que sólo existe durante
      el preprocesado. Por tanto, no ocupa memoria y se puede colocar
      en un fichero de cabecera para ofrecer un valor único a todas
      las unidades que lo utilicen. Es muy importante para el
      mantenimiento del código el uso de sustitución de valores en
      lugar de los también llamados <quote>números mágicos</quote>. Si
      usa números mágicos en su código. no solamente impedirá al
      lector conocer su procedencia o significado si no que complicará
      innecesariamente la edición del código si necesita cambiar
      dicho valor.
    </para>

    <!-- [PAG:355] -->
    <!--
    Most of the time, BUFSIZE will behave like an ordinary variable, but
    not all the time. In addition, there's no type information. This can
    hide bugs that are very difficult to find. C++ uses const to eliminate
    these problems by bringing value substitution into the domain of the
    compiler. Now you can say
    -->
    <para>
      La mayor parte del tiempo, <varname>BUFSIZE</varname> se
      comportará como un valor ordinario, pero no siempre. No tiene
      información de tipo. Eso puede esconder errores difíciles de
      localizar. C++ utiliza <kw>const</kw> para eliminar estos
      problemas llevando la sustitución de valores al terreno del
      compilador. Ahora, puede escribir:
    </para>


<programlisting>
const int bufsize = 100;
</programlisting>

    <!--
    You can use bufsize anyplace where the compiler must know the value at
    compile time. The compiler can use bufsize to perform constant
    folding, which means the compiler will reduce a complicated constant
    expression to a simple one by performing the necessary calculations at
    compile time. This is especially important in array definitions:
    -->
    <para>
      Puede colocar <varname>bufsize</varname> en cualquier lugar
      donde se necesite conocer el valor en tiempo de compilación. El
      compilador utiliza <varname>bufsize</varname> para hacer
      <emphasis>propagación de constantes</emphasis><footnote>
      <para>N. del T.: del inglés <foreignphrase>constant
      folding</foreignphrase></para></footnote>, que significa que el
      compilador reduce una expresión constante complicada a un valor
      simple realizando los cálculos necesarios en tiempo de
      compilación. Esto es especialmente importante en las
      definiciones de vectores:
    </para>


<programlisting>
char buf[bufsize];
</programlisting>

    <!--
    You can use const for all the built-in types (char, int, float, and
    double) and their variants (as well as class objects, as you'll see
    later in this chapter). Because of subtle bugs that the preprocessor
    might introduce, you should always use const instead of #define value
    substitution.
    -->
    <para>
      Puede usar <kw>const</kw> con todos los tipos
      básicos(<type>char</type>, <type>int</type>, <type>float</type>
      y <type>double</type>) y sus variantes (así como clases y todo
      lo que verá después en este capítulo). Debido a los problemas
      que introduce el preprocesador deberá utilizar siempre
      <kw>const</kw> en lugar de <kw>#define</kw> para la sustitución
      de valores.
    </para>

    <sect2>
      <!-- : const in header files -->
      <title><kw>const</kw> en archivos de cabecera</title>

      <!--
      To use const instead of #define, you must be able to place const
      definitions inside header files as you can with #define. This way, you
      can place the definition for a const in a single place and distribute
      it to translation units by including the header file. A const in C++
      defaults to internal linkage; that is, it is visible only within the
      file where it is defined and cannot be seen at link time by other
      translation units. You must always assign a value to a const when you
      define it, except when you make an explicit declaration using extern:
      -->
      <para>
	Para poder usar <kw>const</kw> en lugar de <kw>#define</kw>,
	debe ser posible colocar las definiciones <kw>const</kw> en
	los archivos de cabecera como se hacía con los
	<kw>#define</kw>.  De este modo, puede colocar la definición
	de una constante en un único lugar y distribuirla incluyendo
	el archivo de cabecera en las unidades del programa que la
	necesiten.  Una constante en C++ utiliza <emphasis>enlazado
	interno</emphasis>, es decir, es visible sólo desde el archivo
	donde se define y no puede verse en tiempo de enlazado por
	otros módulos. Deberá asignar siempre un valor a las
	constantes cuando las defina, excepto cuando explícitamente
	use la declaración <kw>extern</kw>:
      </para>
      <!-- [PAG:356] -->


<programlisting>
extern const int bufsize;
</programlisting>

      <!--
      Normally, the C++ compiler avoids creating storage for a const, but
      instead holds the definition in its symbol table. When you use extern
      with const, however, you force storage to be allocated (this is also
      true for certain other cases, such as taking the address of a
      const). Storage must be allocated because extern says "use
      external linkage," which means that several translation units must be
      able to refer to the item, which requires it to have storage.
      -->
      <para>
	Normalmente el compilador de C++ evita la asignación de
	memoria para las constantes, pero en su lugar ocupa una
	entrada en la tabla de símbolos.  Cuando se utiliza
	<kw>extern</kw> con una constante, se fuerza el alojamiento en
	memoria (esto también ocurre en otros casos, como cuando se
	solicita la dirección de una constante). El uso de la memoria
	debe hacerse porque <kw>extern</kw> dice <quote>usa enlazado
	externo</quote>, es decir, que varios módulos deben ser
	capaces de hacer referencia al elemento, algo que requiere su
	almacenamiento en memoria.
      </para>

      <!--
      In the ordinary case, when extern is not part of the definition, no
      storage is allocated. When the const is used, it is simply folded in
      at compile time.
      -->
      <para>
	Por lo general, cuando <kw>extern</kw> no forma parte de
	la definición, no se pide memoria. Cuando la constante se utiliza
	simplemente se incorpora en tiempo de compilación.
      </para>


     <!--
      The goal of never allocating storage for a const also fails with
      complicated structures. Whenever the compiler must allocate storage,
      constant folding is prevented (since there's no way for the compiler
      to know for sure what the value of that storage is - if it could know
      that, it wouldn't need to allocate the storage).
      -->
      <para>
	El objetivo de no almacenar en memoria las constantes tampoco
	se cumple con estructuras complicadas. Cuando el compilador se
	ve obligado a pedir memoria no puede realizar
	<emphasis>propagación de constantes</emphasis> (ya que el
	compilador no tiene forma de conocer con seguridad que valor
	debe almacenar; si lo conociese, no necesitaría pedir
	memoria).
      </para>

      <!--
      Because the compiler cannot always avoid allocating storage for a
      const, const definitions must default to internal linkage, that is,
      linkage only within that particular translation unit. Otherwise,
      linker errors would occur with complicated consts because they cause
      storage to be allocated in multiple cpp files. The linker would then
      see the same definition in multiple object files, and
      complain.

      Because a const defaults to internal linkage, the linker
      doesn't try to link those definitions across translation units, and
      there are no collisions.

      With built-in types, which are used in the
      majority of cases involving constant expressions, the compiler can
      always perform constant folding.
      -->
      <para>
	Como el compilador no siempre puede impedir el almacenamiento
	para una constante, las definiciones de constantes utilizan
	enlace interno, es decir, se enlazan sólo con el módulo en que
	se definen. En caso contrario, los errores de enlace podrían
	ocurrir con las expresiones constantes complicadas ya que
	causarían petición de almacenamiento en diferentes
	módulos. Entonces, el enlazador vería la misma definición en
	múltiples archivos objeto, lo que causaría un error en el
	enlace. Como las constantes utilizan enlace interno, el
	enlazador no intenta enlazar esas definiciones a través de los
	módulos, y así no hay colisiones.  Con los tipos básicos, que
	son los se ven involucrados en la mayoría de los casos, el
	compilador siempre realiza propagación de constantes.
      </para>
    </sect2>


    <sect2>
      <!-- : Safety consts -->
      <title>constantes seguras</title>

      <!--
      The use of const is not limited to replacing #defines in constant
      expressions. If you initialize a variable with a value that is
      produced at runtime and you know it will not change for the
      lifetime of that variable, it is good programming practice to make
      it a const so the compiler will give you an error message if you
      accidentally try to change it. Here's an example:
      -->
      <para>
        El uso de las constantes no está limitado a la sustitución de
        los <kw>#define</kw> por expresiones constantes. Si inicializa
        una variable con un valor que se produce en tiempo de ejecución
        y sabe que no cambiará durante la
	<!-- [PAG:357] --> vida de la variable, es una buena práctica
        de programación hacerla constante para que de ese modo el
        compilador produzca un mensaje de error si accidentalmente
        alguien intenta modificar dicha variable. Aquí hay un ejemplo:
      </para>


//: V1C08:Safecons.cpp


      <!--
      You can see that i is a compile-time const, but j is calculated from
      i. However, because i is a const, the calculated value for j still
      comes from a constant expression and is itself a compile-time
      constant. The very next line requires the address of j and therefore
      forces the compiler to allocate storage for j. Yet this doesn't
      prevent the use of j in the determination of the size of buf because
      the compiler knows j is const and that the value is valid even if
      storage was allocated to hold that value at some point in the program.
      -->
      <para>
        Puede ver que <constant>i</constant> es una constante en
        tiempo de compilación, pero <constant>j</constant> se calcula
        a partir de <constant>i</constant>. Sin embargo, como
        <constant>i</constant> es una constante, el valor calculado
        para <constant>j</constant> es una expresión constante y es en
        si mismo otra constante en tiempo de compilación. En la
        siguiente línea se necesita la dirección de
        <constant>j</constant> y por lo tanto el compilador se ve
        obligado a pedir almacenamiento para
        <constant>j</constant>. Ni siquiera eso impide el uso de
        <constant>j</constant> para determinar el tamaño de
        <varname>buf</varname> porque el compilador sabe que
        <constant>j</constant> es una constante y que su valor es
        válido aunque se asigne almacenamiento, ya que eso se hace
        para mantener el valor en algún punto en el programa.
      </para>


      <!--
      In main( ), you see a different kind of const in the identifier c
      because the value cannot be known at compile time. This means
      storage is required, and the compiler doesn't attempt to keep
      anything in its symbol table (the same behavior as in C). The
      initialization must still happen at the point of definition, and
      once the initialization occurs, the value cannot be changed. You
      can see that c2 is calculated from c and also that scoping works
      for consts as it does for any other type - yet another improvement
      over the use of #define
      -->
      <para>
        En <function>main()</function>, aparece un tipo diferente de
        constante en el identificador <constant>c</constant>, porque el
        valor no puede ser conocido en tiempo de compilación. Eso
        significa que se requiere almacenamiento, y por eso el
        compilador no intenta mantener nada en la tabla de símbolos (el
        mismo comportamiento que en C). La inicialización debe ocurrir,
        aún así, en el punto de la definición, y una vez que ocurre la
        inicialización, el valor ya no puede ser cambiado. Puede ver que
        <constant>c2</constant> se calcula a partir de
        <constant>c</constant> y además las reglas de ámbito funcionan
        para las constantes igual que para cualquier otro tipo, otra
        ventaja respecto al uso de <kw>#define</kw>.
      </para>

      <!-- [PAG:358] -->
      <!--
      As a matter of practice, if you think a value shouldn't change, you
      should make it a const. This not only provides insurance against
      inadvertent changes, it also allows the compiler to generate more
      efficient code by eliminating storage and memory reads.
      -->
      <para>
	En la práctica, si piensa que una variable no debería cambiar,
	debería hacer que fuese una constante. Esto no sólo da seguridad
	contra cambios inadvertidos, también permite al compilador
	generar código más eficiente ahorrando espacio de almacenamiento
	y lecturas de memoria en la ejecución del programa.
      </para>
    </sect2>

    <sect2>
      <!-- : Aggregates -->
      <title>Vectores</title>

      <!--
      It's possible to use const for aggregates, but you're virtually
      assured that the compiler will not be sophisticated enough to keep an
      aggregate in its symbol table, so storage will be allocated. In these
      situations, const means "a piece of storage that cannot be
      changed." However, the value cannot be used at compile time because
      the compiler is not required to know the contents of the storage at
      compile time. In the following code, you can see the statements that
      are illegal:
      -->
      <para>
	Es posible usar constantes para los vectores, pero
	prácticamente está dando por hecho que el compilador no será
	lo suficientemente sofisticado para mantener un vector en la
	tabla de símbolos, así que le asignará espacio de
	almacenamiento. En estas situaciones, <kw>const</kw> significa
	<quote>un conjunto de datos en memoria que no pueden
	modificarse</quote>. En cualquier caso, sus valores no puede
	usarse en tiempo de compilación porque el compilador no conoce
	en ese momento los contenidos de las variables que tienen
	espacio asignado. En el código siguiente puede ver algunas
	declaraciones incorrectas.
      </para>


//: V1C08:Constag.cpp


      <!--
      In an array definition, the compiler must be able to generate code
      that moves the stack pointer to accommodate the array. In both of the
      illegal definitions above, the compiler complains because it cannot
      find a constant expression in the array definition.
      -->
      <para>
	En la definición de un vector, el compilador debe ser capaz de
	generar código que mueva el puntero de pila para dar cabida al
	vector. En las definiciones incorrectas anteriores, el
	compilador se queja porque no puede encontrar una expresión
	constante en la definición del tamaño del vector.
      </para>
    </sect2>

    <sect2>
      <!-- : Differences with C -->
      <title>Diferencias con C</title>

      <!--
      Constants were introduced in early versions of C++ while the Standard
      C specification was still being finished. Although the C committee
      then decided to include const in C, somehow it came to mean for them
      "an ordinary variable that cannot be changed." In C, a const always
      occupies storage and its name is global. The C compiler cannot treat a
      const as a compile-time constant. In C, if you say
      -->
      <para>
	Las constantes se introdujeron en las primeras versiones de
	C++ mientras la especificación del estándar C estaba siendo
	terminada. Aunque el comité a cargo de C decidió entonces
	incluir <kw>const</kw> en C, por alguna razón, vino
	a significar para ellos <quote>una variable ordinaria que no
	puede cambiarse</quote>. En C, una constante siempre ocupa
	espacio de almacenamiento y su ámbito es global. El compilador
	C no puede tratar <kw>const</kw> como una constante
	en tiempo de compilación. En C, si escribe:
      </para>
      <!-- [PAG:359] -->


<programlisting>
const int bufsize = 100;
char buf[bufsize];
</programlisting>

      <!--
      you will get an error, even though it seems like a rational thing to
      do. Because bufsize occupies storage somewhere, the C compiler cannot
      know the value at compile time. You can optionally say
      -->
      <para>
	aparecerá un error, aunque parezca algo
	razonable. <constant>bufsize</constant> está guardado en algún
	sitio y el compilador no conoce su valor en tiempo de
	compilación. Opcionalmente puede escribir:
      </para>


<programlisting>
const int bufsize;
</programlisting>

      <!--
      in C, but not in C++, and the C compiler accepts it as a declaration
      indicating there is storage allocated elsewhere. Because C defaults to
      external linkage for consts, this makes sense. C++ defaults to
      internal linkage for consts so if you want to accomplish the same
      thing in C++, you must explicitly change the linkage to external using
      extern:
      -->
      <para>
	en C, pero no en C++, y el compilador C lo acepta como una
	declaración que indica que se almacenará en alguna parte. Como
	C utiliza enlace externo para las constantes, esa semántica
	tiene sentido. C++ utiliza normalmente enlace interno, así
	que, si quiere hacer lo mismo en C++, debe indicar
	expresamente que se use enlace externo usando <kw>extern</kw>.
      </para>


<programlisting>
extern const int bufsize;  // es declaración, no definición
</programlisting>


      <!-- This line also works in C. -->
      <para>
        Esta declaración también es válida en C.
      </para>

      <!--
      In C++, a const doesn't necessarily create storage. In C a const
      always creates storage. Whether or not storage is reserved for a const
      in C++ depends on how it is used. In general, if a const is used
      simply to replace a name with a value (just as you would use a
      #define), then storage doesn't have to be created for the const. If no
      storage is created (this depends on the complexity of the data type
      and the sophistication of the compiler), the values may be folded into
      the code for greater efficiency after type checking, not before, as
      with #define. If, however, you take an address of a const (even
      unknowingly, by passing it to a function that takes a reference
      argument) or you define it as extern, then storage is created for the
      const.
      -->
      <para>
        En C++, <kw>const</kw> no implica necesariamente
        almacenamiento. En C, las constantes siempre necesitan
        almacenamiento. El hecho de que se necesite almacenamiento o no
        depende de cómo se use la constante. En general, si una
        constante se usa simplemente para reemplazar un número por un
        nombre (como hace <kw>#define</kw>), entonces no requiere
        almacenamiento. Si es así (algo que depende de la complejidad
        del tipo de dato y de lo sofisticación del compilador) los
        valores pueden expandirse en el código para conseguir mayor
        eficiencia después de la comprobación de los tipos, no como con
        <kw>#define</kw>. Si de todas formas, se necesita la dirección
        de una constante (aún desconocida, para pasarla a una función
        como argumento por referencia) o se declara como
        <kw>extern</kw>, entonces se requiere asignar almacenamiento
        para la constante.
      </para>

      <!--
      In C++, a const that is outside all functions has file scope (i.e., it
      is invisible outside the file). That is, it defaults to internal
      linkage. This is very different from all other identifiers in C++ (and
      from const in C!) that default to external linkage. Thus, if you
      declare a const of the same name in two different files and you don't
      take the address or define that name as extern, the ideal C++ compiler
      won't allocate storage for the const, but simply fold it into the
      code. Because const has implied file scope, you can put it in C++
      header files with no conflicts at link time.
      -->
      <para>
        En C++, una constante que esté definida fuera de todas las
        funciones tiene ámbito de archivo (es decir, es inaccesible
        fuera del archivo). Esto significa que usa enlace
        interno. Esto es diferente para el resto de identificadores en
        C++ (y que las constantes en C) que utilizan siempre enlace
        externo. Por eso, si declara una constante con el mismo nombre
        en dos archivos diferentes y no toma sus
	<!-- [PAG:360] -->
        direcciones ni los define como <kw>extern</kw>, el compilador
        C++ ideal no asignará almacenamiento para la constante,
        simplemente la expandirá en el código. Como las constantes
        tienen implícito el ámbito a su archivo, puede ponerlas en un
        archivo de cabecera de C++ sin que origine conflictos en el
        enlace.
      </para>

      <!--
      Since a const in C++ defaults to internal linkage, you can't just
      define a const in one file and reference it as an extern in another
      file. To give a const external linkage so it can be referenced from
      another file, you must explicitly define it as extern, like this:
      -->
      <para>
	Dado que las constante en C++ utilizan por defecto enlace
	interno, no puede definir una constante en un archivo y
	utilizarla desde otro. Para conseguir enlace externo para la
	constante y así poder usarla desde otro archivo, debe
	definirla explícitamente como <kw>extern</kw>, algo
	así:
      </para>


<programlisting>
extern const int x = 1;  // definición, no declaración
</programlisting>


      <!--
      Notice that by giving it an initializer and saying it is extern, you
      force storage to be created for the const (although the compiler still
      has the option of doing constant folding here). The initialization
      establishes this as a definition, not a declaration. The declaration:
      -->
      <para>
	Señalar que dado un identificador, si se dice que es
	<kw>extern</kw>, se fuerza el almacenamiento para la
	constante (aunque el compilador tenga la opción de hacer la
	expansión en ese punto). La inicialización establece que la
	sentencia es una definición, no una declaración. La
	declaración:
      </para>


<programlisting>
extern const int x;
</programlisting>


      <!--
      in C++ means that the definition exists elsewhere (again, this is not
      necessarily true in C). You can now see why C++ requires a const
      definition to have an initializer: the initializer distinguishes a
      declaration from a definition (in C it's always a definition, so no
      initializer is necessary). With an extern const declaration, the
      compiler cannot do constant folding because it doesn't know the value.
      -->
      <para>
	en C++ significa que la definición existe en algún sitio
	(mientras que en C no tiene porqué ocurrir así). Ahora puede
	ver porqué C++ requiere que las definiciones de constantes
	incluyan la inicialización: la inicialización diferencia una
	declaración de una definición (en C siempre es una definición,
	aunque no esté inicializada). Con una declaración <kw>const
	extern</kw>, el compilador no hace expansión de la constante
	porque no conoce su valor.
      </para>

      <!--
      The C approach to const is not very useful, and if you want to use a
      named value inside a constant expression (one that must be evaluated
      at compile time), C almost forces you to use #define in the
      preprocessor.
      -->
      <para>
	La aproximación de C a las constantes es poco útil, y si quiere
	usar un valor simbólico en una expresión constante (que deba
	evaluarse en tiempo de compilación) casi está obligado a usar
	<kw>#define</kw>.
      </para>
    </sect2>
  </sect1>




  <sect1>
    <!-- : Pointers -->
    <title>Punteros</title>

    <!--
    Pointers can be made const. The compiler will still endeavor to
    prevent storage allocation and do constant folding when dealing with
    const pointers, but these features seem less useful in this case. More
    importantly, the compiler will tell you if you attempt to change a
    const pointer, which adds a great deal of safety.
    -->
    <!--
    When using const with pointers, you have two options: const can be
    applied to what the pointer is pointing to, or the const can be
    applied to the address stored in the pointer itself. The syntax for
    these is a little confusing at first but becomes comfortable with
    practice.
    -->
    <para>
      Los punteros pueden ser constantes. El compilador pondrá más
      esfuerzo aún para evitar el almacenamiento y hacer expansión de
      constantes cuando se trata de punteros constantes, pero estas
      características parecen menos útiles en este caso.
      <!-- [PAG:361] -->
      Lo más importante es que el compilador le avisará si intenta
      cambiar un puntero constante, lo que representa un buen elemento
      de seguridad. Cuando se usa <kw>const</kw> con punteros tiene dos
      opciones: se pueden aplicar a lo que apunta el puntero o a la
      propia dirección almacenada en el puntero. La sintaxis es un poco
      confusa al principio pero se vuelve cómodo con la práctica.
    </para>



    <sect2>
      <!-- : Pointer to const -->
      <title>Puntero a constante</title>

      <!--
      The trick with a pointer definition, as with any complicated
      definition, is to read it starting at the identifier and work your way
      out. The const specifier binds to the thing it is "closest to." So
      if you want to prevent any changes to the element you are pointing to,
      you write a definition like this:
      -->
      <para>
	El truco con la definición de un puntero, al igual que con una
	definición complicada, es leerla empezando por el
	identificador e ir analizando la definición hacia afuera. El
	especificador <kw>const</kw> está ligado a la cosa
	<quote>más cercana</quote>.  Así que si se quiere impedir
	cambios en el elemento apuntado, escribe una definición
	parecida a esta:
      </para>


<programlisting>
const int* u;
</programlisting>


      <!--
      Starting from the identifier, we read "u is a pointer, which points to
      a const int." Here, no initialization is required because you're
      saying that u can point to anything (that is, it is not const), but
      the thing it points to cannot be changed.
      -->
      <para>
	Empezando por el identificador, se lee
	<quote><varname>u</varname> es un puntero, que apunta a un
	entero constante</quote>. En este caso no se requiere
	inicialización porque está diciendo que <varname>u</varname>
	puede apuntar a cualquier cosa (es decir, no es constante),
	pero la cosa a la que apunta no puede cambiar.
      </para>


      <!--
      Here's the mildly confusing part. You might think that to make the
      pointer itself unchangeable, that is, to prevent any change to the
      address contained inside u, you would simply move the const to the
      other side of the int like this:
      -->
      <para>
	Ahora viene la parte confusa. Podría pensar que hacer el puntero
	inalterable en si mismo, es decir, impedir cualquier cambio en
	la dirección que contiene <varname>u</varname>, es tan simple
	como mover la palabra <kw>const</kw> al otro lado de la
	palabra <type>int</type>:
      </para>


<programlisting>
int const* v;
</programlisting>

      <!--
      It's not all that crazy to think that this should read "v is a
      const pointer to an int." However, the way it actually reads is "v is
      an ordinary pointer to an int that happens to be const." That is, the
      const has bound itself to the int again, and the effect is the same as
      the previous definition. The fact that these two definitions are the
      same is the confusing point; to prevent this confusion on the part of
      your reader, you should probably stick to the first form.
      -->
      <para>
	y pensar que esto debería leerse <quote><varname>v</varname>
	es un puntero constante a un entero</quote>. Sin embargo, la
	forma de leerlo es <quote><varname>v</varname> es un puntero
	ordinario a un entero que es constante</quote>. Es decir, la
	palabra <kw>const</kw> se refiere de nuevo al
	<type>entero</type> y el efecto es el mismo que en la
	definición previa.  El hecho de que estas definiciones sean
	equivalentes es confuso, para evitar esta confusión por parte
	del lector del código, debería ceñirse a la primera forma.
      </para>
      <!-- [PAG:362] -->
    </sect2>

    <sect2>
      <!-- : const pointer -->
      <title>Puntero constante</title>

     <!--
      To make the pointer itself a const, you must place the const specifier
      to the right of the *, like this:
      -->
      <para>
	Para conseguir que el puntero sea inalterable, debe colocar el
	especificador <kw>const</kw> a la derecha del *:
      </para>


<programlisting>
int d = 1;
int * const w = &amp;d;
</programlisting>

      <!--
      Now it reads: "w is a pointer, which is const, that points to an int."
      Because the pointer itself is now the const, the compiler requires
      that it be given an initial value that will be unchanged for the life
      of that pointer. It's OK, however, to change what that value points to
      by saying
      -->
      <para>
	Ahora, se lee <quote><constant>w</constant> es un puntero
	constate, y apunta a un <type>entero</type></quote>. Como el
	puntero en sí es ahora una constante, el compilador obliga a
	darle un valor inicial que no podrá alterarse durante la vida
	del puntero. En cualquier caso, puede cambiar el valor de lo
	que apunta el puntero con algo como:
      </para>


<programlisting>
*w = 2;
</programlisting>

      <!--
      You can also make a const pointer to a const object using either of
      two legal forms:
      -->
      <para>
	También puede hacer un puntero constante a un elemento constante
	usando una de las formas siguientes:
      </para>


<programlisting>
int d = 1;
const int* const x = &amp;d;  // (1)
int const* const x2 = &amp;d; // (2)
</programlisting>


      <!--
      Now neither the pointer nor the object can be changed.
      -->
      <para>
        Ahora ni el puntero ni el elemento al que apunta pueden
        modificarse.
      </para>

      <!--
      Some people argue that the second form is more consistent because the
      const is always placed to the right of what it modifies. You'll have
      to decide which is clearer for your particular coding style.
      -->
      <para>
	Algunos argumentan que la segunda forma es más consistente
	porque el <kw>const</kw> se coloca siempre a la derecha de lo
	que afecta. Debe decidir que forma resulta más clara para su
	estilo de codificación particular.
      </para>

      <!-- Here are the above lines in a compileable file: -->
      <para>
	Algunas líneas de un archivo susceptible de ser compilado.
      </para>



//: V1C08:ConstPointers.cpp



      <sect3>
        <!-- : Formatting -->
        <title>Formato</title>

        <!-- [PAG:363] -->
        <!--
        This book makes a point of only putting one pointer definition
        on a line, and initializing each pointer at the point of
        definition whenever possible. Because of this, the formatting
        style of "attaching" the '*' to the data type is possible:
        -->

        <para>
          Este libro sigue la norma de poner sólo una definición de
          puntero por línea, e inicializar cada puntero en el punto de
          definición siempre que sea posible. Por eso, el estilo es
          colocar el <symbol>*</symbol> al lado del tipo:
        </para>


<programlisting>
int* u = &amp;i;
</programlisting>


        <!--
        as if int* were a discrete type unto itself. This makes the code
        easier to understand, but unfortunately that's not actually the way
        things work. The "*" in fact binds to the identifier, not the type. It
        can be placed anywhere between the type name and the identifier. So
        you could do this:
        -->
	<para>
	  como si <type>int*</type> fuese un tipo de dato básico. Esto
	  hace que el código sea más fácil de leer, pero
	  desafortunadamente, esta no es la forma en que funciona. El
	  <quote><symbol>*</symbol></quote> se refiere al
	  identificador no al tipo. Se puede colocar en cualquier
	  sitio entre el nombre del tipo y el identificador. De modo
	  que puede hacer esto:
	</para>


<programlisting>
int * u = &amp;i, v = 0;
</programlisting>

        <!--
        which creates an int* u, as before, and a non-pointer int v. Because
        readers often find this confusing, it is best to follow the form shown
        in this book.
        -->
	<para>
	  donde se crea un <code>int* u</code> y después un <code>int
	 v</code> (que no es puntero). Como esto puede parecer confuso
	 a los lectores, es mejor utilizar el estilo mostrado en este
	 libro.
	</para>
      </sect3>
    </sect2>

    <sect2>
      <!-- : Assignment and type checking -->
      <title>Asignación y comprobación de tipos</title>

      <!--
      C++ is very particular about type checking, and this extends to
      pointer assignments. You can assign the address of a non-const object
      to a const pointer because you're simply promising not to change
      something that is OK to change. However, you can't assign the address
      of a const object to a non-const pointer because then you're saying
      you might change the object via the pointer. Of course, you can always
      use a cast to force such an assignment, but this is bad programming
      practice because you are then breaking the constness of the object,
      along with any safety promised by the const. For example:
      -->
      <para>
	C++ es muy exigente en lo referente a la comprobación de tipos
	y esto se extiende a la asignación de punteros. Puede asignar
	la dirección de una variable no constante a un puntero
	constante porque simplemente está prometiendo no cambiar algo
	que puede cambiarse. De todos modos, no puede asignar la
	dirección de una variable constante a un puntero no constante
	porque entonces está diciendo que podría modificar la variable
	a través del puntero. Por supuesto, siempre puede usar
	<quote>un molde</quote> para forzar la asignación, pero eso es
	siempre una mala práctica de programación ya que rompe la
	consistencia de la variable además del grado de seguridad que
	ofrece el especificador <kw>const</kw>. Por ejemplo:
      </para>



//: V1C08:PointerAssignment.cpp



      <!-- [PAG:364] -->
      <!--
      Although C++ helps prevent errors it does not protect you from
      yourself if you want to break the safety mechanisms.
      -->
      <para>
	Aunque C++ ayuda a evitar errores, no le protege de usted
	mismo si se empeña en romper los mecanismos de seguridad.
      </para>

      <sect3>
        <!-- : Character array literals -->
	<title>Literales de cadena</title>

        <!--
        The place where strict constness is not enforced is with character
        array literals. You can say
        -->
	<para>
	  C++ no es tan estricto con los literales en lo referente a
	  constantes. Puede escribir:
	</para>


<programlisting>
char * cp = "howdy";
</programlisting>


        <!--
        and the compiler will accept it without complaint. This is technically
        an error because a character array literal ("howdy" in this case)
        is created by the compiler as a constant character array, and the
        result of the quoted character array is its starting address in
        memory. Modifying any of the characters in the array is a runtime
        error, although not all compilers enforce this correctly.
        -->
	<para>
	  y el compilador lo aceptará sin objeción. Técnicamente esto
	  supone un error porque el literal de cadena
	  (<quote><literal>howdy</literal></quote> en este caso) se crea
	  por el compilador como un vector de caracteres constante, y el
	  resultado del vector de caracteres entrecomillado es la
	  dirección de memoria del primer elemento. Si se modifica uno
	  de los caracteres del vector en tiempo de ejecución es un
	  error, aunque no todos los compiladores lo imponen
	  correctamente.
	</para>


        <!--
        So character array literals are actually constant character arrays. Of
        course, the compiler lets you get away with treating them as non-const
        because there's so much existing C code that relies on this. However,
        if you try to change the values in a character array literal, the
        behavior is undefined, although it will probably work on many
        machines.
        -->
	<para>
	  Así que los literales de cadena son arrays de caracteres
	  constantes. Por supuesto, el compilador le permite tratarlos como
	  no constantes porque existe mucho código C que depende de ello. De
	  todas formas, si intenta cambiar los valores de un literal, el
	  resultado no está definido, y probablemente funcione en muchos
	  computadores.
	</para>

        <!-- If you want to be able to modify the string, put it in an
        array: -->
	<para>
	  Si quiere poder modificar una cadena, debe ponerla en un vector:
	</para>


<programlisting>
char cp[] = "howdy";
</programlisting>

        <!--
        Since compilers often don't enforce the difference you won't be
        reminded to use this latter form and so the point becomes rather
        subtle.
        -->
	<para>
	  Como los compiladores a menudo no imponen la diferencia no
	  tiene porqué recordar que debe usar esta la última forma y
	  la cuestión pasa a ser algo bastante sutil.
	</para>
      </sect3>
    </sect2>
  </sect1>


  <sect1>
    <!-- : Function arguments & return values -->
    <title>Argumentos de funciones y valores de retorno</title>

    <!--
    The use of const to specify function arguments and return values is
    another place where the concept of constants can be confusing. If you
    are passing objects by value, specifying const has no meaning to the
    client (it means that the passed argument cannot be modified inside
    the function). If you are returning an object of a user-defined type
    by value as a const, it means the returned value cannot be
    modified. If you are passing and returning addresses, const is a
    promise that the destination of the address will not be changed.
    -->
    <para>
      El uso del especificador <kw>const</kw> con argumentos de
      funciones y valores de retorno es otro lugar donde el concepto
      de constante puede resultar confuso.  Si está pasando variables
      por valor, utilizar <kw>const</kw> no tiene significado para el
      cliente (significa que el argumento que se pasa no puede
      modificarse en la función). Si está devolviendo una variable de
      un tipo derivado y utiliza el especificador <kw>const</kw>,
      significa que el valor de retorno no puede modificarse. Si pasa
      o devuelve direcciones, <kw>const</kw> impide que el
      destinatario de la dirección pueda modificarse.
    </para>

    <sect2>
      <!-- : Passing by const value -->
      <title>Paso por valor constante</title>

      <!--
      You can specify that function arguments are const when passing them by
      value, such as
      -->
      <para>
	Puede indicar que los argumentos de funciones son constantes
	cuando se pasa por valor como:
      </para>


<programlisting>
void f1(const int i) {
    i++; // ilegal
}
</programlisting>

      <!--
      but what does this mean? You're making a promise that the original
      value of the variable will not be changed by the function f1(
      ). However, because the argument is passed by value, you immediately
      make a copy of the original variable, so the promise to the client is
      implicitly kept.
      -->
      <para>
	pero, ¿qué significa esto? Está impidiendo que el valor de la
	variable original pueda ser cambiado en la función
	<function>f1()</function>. De todos formas, como el
	argumento se pasa por valor, es sabido que inmediatamente se
	hace una copia de la variable original, así que dicha
	restricción se cumple implícitamente sin necesidad de usar
	el especificador <kw>const</kw>.
      </para>

      <!--
      Inside the function, the const takes on meaning: the argument cannot
      be changed. So it's really a tool for the creator of the function, and
      not the caller.
      -->
      <para>
	Dentro de la función, <kw>const</kw> si toma un significado:
	El argumento no se puede cambiar. Así que, en realidad, es una
	herramienta para el programador de la función, no para el que
	la usa.
      </para>

     <!--
      To avoid confusion to the caller, you can make the argument a const
      inside the function, rather than in the argument list. You could do
      this with a pointer, but a nicer syntax is achieved with the
      reference, a subject that will be fully developed in Chapter
      11.

      Briefly, a reference is like a constant pointer that is
      automatically dereferenced, so it has the effect of being an
      alias to an object. To create a reference, you use the & in the
      definition. So the non-confusing function definition looks like
      this: -->
      <para>
	Para evitar la confusión del usuario de la función, puede hacer
	que el argumento sea constante dentro de la función en lugar de en
	la lista de argumentos. Podría hacerlo con un puntero, pero la
	sintaxis más adecuada para lograrlo es la referencia, algo que se
	tratará en profundidad en el capitulo 11[FIXME:XREF].
      </para>

      <!-- FIXME -->
      <para>
	Brevemente, una referencia es como un puntero constante que
	se dereferencia automáticamente, así que es como tener un
	alias de la variable. Para crear una referencia, debe usar
	el símbolo <symbol>&amp;</symbol> en la definición. De ese
	modo se tiene una definición libre de confusiones.
      </para>


<programlisting>
void f2(int ic) {
    const int &amp;i = ic;
    i++;  // ilegal (error de compilación)
}
</programlisting>

      <!--
      Again, you'll get an error message, but this time the constness of the
      local object is not part of the function signature; it only has
      meaning to the implementation of the function and therefore it's
      hidden from the client.
      -->
      <para>
	De nuevo, aparece un mensaje de error, pero esta vez el
	especificador <kw>const</kw> no forma parte de la
	cabecera de la función, solo tiene sentido en la
	implementación de la función y por la tanto es invisible para
	el cliente.
      </para>
    </sect2>

    <sect2>
      <!-- : Returning by const value -->
      <title>Retorno por valor constante</title>

      <!--
      A similar truth holds for the return value. If you say that a
      function's return value is const:
      -->      <para>
	Algo similar ocurre con los valores de retorno. Si dice que el
	valor de retorno de una función es constante:
      </para>


<programlisting>
const int g();
</programlisting>


      <!--
      you are promising that the original variable (inside the function
      frame) will not be modified. And again, because you're returning it by
      value, it's copied so the original value could never be modified via
      the return value.
      -->
      <para>
	está diciendo que el valor de la variable original (en el ámbito de
	la función) no se modificará. Y de nuevo, como lo está devolviendo
	por valor, es la copia lo que se retorna, de modo que el valor
	original nunca se podrá modificar.
      </para>

      <!--
      At first, this can make the specification of const seem
      meaningless. You can see the apparent lack of effect of returning
      consts by value in this example:
      -->
      <para>
	En principio, esto puede hacer suponer que el especificador
	<kw>const</kw> tiene poco significado. Puede ver la aparente
	falta de sentido de devolver constantes por valor en este
	ejemplo:
      </para>



//: V1C08:Constval.cpp


      <!--
      For built-in types, it doesn't matter whether you return by value as a
      const, so you should avoid confusing the client programmer and leave
      off the const when returning a built-in type by value.
      -->
      <para>
	Para los tipos básicos, no importa si el retorno es
	constante, así que debería evitar la confusión para el
	programador cliente y no utilizar <kw>const</kw>
	cuando se devuelven variables de tipos básicos por valor.
      </para>

      <!--
      Returning by value as a const becomes important when you're dealing
      with user-defined types. If a function returns a class object by value
      as a const, the return value of that function cannot be an lvalue
      (that is, it cannot be assigned to or otherwise modified). For
      example:
      -->
      <para>
	Devolver por valor como constante se vuelve importante cuando
	se trata con tipos definidos por el programador. Si una
	función devuelve un objeto por valor como constante, el valor
	de retorno de la función no puede ser un recipiente
	<footnote><para>N. del T.: <quote>recipiente</quote>
	corresponde con el término
	<foreignphrase>lvalue</foreignphrase> que se refiere a una
	variable que puede ser modificada o a la que se le puede
	asignar un valor.</para></footnote>
      </para>

      <para>
	Por ejemplo:
      </para>


//: V1C08:ConstReturnValues.cpp


      <!--
      f5( ) returns a non-const X object, while f6( ) returns a const X
      object. Only the non-const return value can be used as an
      lvalue. Thus, it's important to use const when returning an object by
      value if you want to prevent its use as an lvalue.
      -->
      <para>
	<function>f5()</function> devuelve un objeto de clase
	<classname>X</classname> no constante, mientras que
	<function>f6()</function> devuelve un objeto de clase
	<classname>X</classname> pero constante. Solo el valor de
	retorno por valor no constante se puede usar como recipiente.
      </para>

      <para>
	Por eso, es importante usar <kw>const</kw> cuando se devuelve
	un objeto por valor si quiere impedir que se use como
	recipiente.
      </para>

      <!--
      The reason const has no meaning when you're returning a built-in type
      by value is that the compiler already prevents it from being an lvalue
      (because it's always a value, and not a variable). Only when you're
      returning objects of user-defined types by value does it become an
      issue.
      -->
      <para>
	La razón por la que <kw>const</kw> no tiene sentido cuando se
	usa para devolver por valor variables de tipos del lenguaje es
	que el compilador impide automáticamente el uso de dichos
	tipos como recipiente, ya que devuelve un valor, no una
	variable. Solo cuando se devuelven objetos por valor de tipos
	definidos por el programador esta funcionalidad toma
	sentido.
      </para>

      <!-- The function f7( ) takes its argument as a non-const
      reference (an additional way of handling addresses in C++ and
      the subject of Chapter 11). This is effectively the same as
      taking a non-const pointer; it's just that the syntax is
      different. The reason this won't compile in C++ is because of
      the creation of a temporary.  -->
      <para>
	La función <function>f7()</function> toma como argumento una
	referencia no constante (la referencia es una forma adicional
	para manejar direcciones en C++ y se trata en el
	[FIXME:XREF:capitulo 11]). Es parecido a tomar un puntero no
	constante, aunque la sintaxis es diferente. La razón por la
	que no compila es por la creación de un temporario.
      </para>

      <sect3>
	<!-- : Temporaries -->
	<title>Temporarios</title>

        <!--
        Sometimes, during the evaluation of an expression, the compiler must
        create temporary objects. These are objects like any other: they
        require storage and they must be constructed and destroyed. The
        difference is that you never see them - the compiler is responsible
        for deciding that they're needed and the details of their
        existence. But there is one thing about temporaries: they're
        automatically const. Because you usually won't be able to get your
        hands on a temporary object, telling it to do something that will
        change that temporary is almost certainly a mistake because you won't
        be able to use that information. By making all temporaries
        automatically const, the compiler informs you when you make that
        mistake.
        -->
	<para>
	  A veces, durante la evaluación de una expresión, el compilador
	  debe crear objetos temporales (temporarios). Son objetos como
	  cualquier otro: requieren espacio de almacenamiento y se deben
	  construir y destruir. La diferencia es que nunca se ven, el
	  compilador es el responsable de decidir si se necesitan y los
	  detalles de su existencia. Una particularidad importante de los
	  temporarios es que siempre son constantes. Como normalmente no
	  manejará objetos temporarios, hacer algo que cambie un temporario
	  es casi seguro un error porque no será capaz de usar esa
	  información. Para evitar esto, el compilador crea todos los
	  temporarios como objetos constantes, de modo que le avisará si
	  intenta modificarlos.
	</para>

        <!--
        In the above example, f5( ) returns a non-const X object. But in the
        expression:
        -->
	<para>
	  En el ejemplo anterior, <function>f5()</function> devuelve
	  un objeto no constante. Pero en la expresión:
	</para>


<programlisting>
f7(f5());
</programlisting>

        <!-- the compiler must manufacture a temporary object to hold
        the return value of f5( ) so it can be passed to f7( ). This
        would be fine if f7( ) took its argument by value; then the
        temporary would be copied into f7( ) and it wouldn't matter
        what happened to the temporary X.

	However, f7( ) takes its argument by reference, which means in
        this example takes the address of the temporary X.  Since f7(
        ) doesn't take its argument by const reference, it has
        permission to modify the temporary object. But the compiler
        knows that the temporary will vanish as soon as the expression
        evaluation is complete, and thus any modifications you make to
        the temporary X will be lost. By making all temporary objects
        automatically const, this situation causes a compile-time
        error message so you don't get caught by what would be a very
        difficult bug to find.  -->
	<para>
	  el compilador debe crear un temporario para albergar el
	  valor de retorno de <function>f5()</function> para que pueda
	  ser pasado a <function>f7()</function>. Esto funcionaría
	  bien si <function>f7()</function> tomara su argumento por
	  valor; entonces el temporario se copiaría en
	  <function>f7()</function> y no importaría lo que se pase al
	  temporario X.
	</para>

	<!-- FIXME -->
	<para>
	  Sin embargo, <function>f7()</function> toma su argumento por
	  referencia, lo que significa que toma la dirección del
	  temporario X. Como <function>f7()</function> no toma su
	  argumento por referencia constante, tiene permiso para
	  modificar el objeto temporario. Pero el compilador sabe que
	  el temporario desaparecerá en cuanto se complete la
	  evaluación de la expresión, y por eso cualquier modificación
	  hecha en el temporario se perderá.  Haciendo que los objetos
	  temporarios sean constantes automáticamente, la situación
	  causa un error de compilación de modo que evitará cometer un
	  error muy difícil de localizar.
	</para>

        <!-- However, notice the expressions that are legal: -->
	<para>
	  En cualquier caso, tenga presente que las expresiones
	  siguientes son correctas:
	</para>


<programlisting>
f5() = X(1);
f5().modify();
</programlisting>

       <!--
        Although these pass muster for the compiler, they are actually
        problematic. f5( ) returns an X object, and for the compiler to
        satisfy the above expressions it must create a temporary to hold that
        return value. So in both expressions the temporary object is being
        modified, and as soon as the expression is over the temporary is
        cleaned up. As a result, the modifications are lost so this code is
        probably a bug - but the compiler doesn't tell you anything about
        it. Expressions like these are simple enough for you to detect the
        problem, but when things get more complex it's possible for a bug to
        slip through these cracks.
        -->
	<para>
	  Aunque son aceptables para el compilador, en realidad son
	  problemáticas.  <function>f5()</function> devuelve un
	  objeto de clase <classname>X</classname>, y para que el
	  compilador pueda satisfacer las expresiones anteriores
	  debe crear un temporario para albergar el valor de
	  retorno. De modo que en ambas expresiones el objeto
	  temporario se modifica y tan pronto como la expresión es
	  evaluada el temporario se elimina. Como resultado, las
	  modificaciones se pierden, así que probablemente este
	  código es erróneo, aunque el compilador no diga nada al
	  respecto. Las expresiones como éstas son suficientemente
	  simples como para detectar el problema, pero cuando las
	  cosas son más complejas los errores son más difíciles de
	  localizar.
	</para>

        <!--
        The way the constness of class objects is preserved is shown later in
        the chapter.
        -->
	<para>
	  La forma de preservar la constancia de los objetos se
	  muestra más adelante en este capítulo.
	</para>
      </sect3>
    </sect2>

    <sect2>
      <!-- : Passing and returning addresses -->
      <title>Paso y retorno de direcciones</title>

      <!--
      If you pass or return an address (either a pointer or a reference),
      it's possible for the client programmer to take it and modify the
      original value. If you make the pointer or reference a const, you
      prevent this from happening, which may save you some grief. In fact,
      whenever you're passing an address into a function, you should make it
      a const if at all possible. If you don't, you're excluding the
      possibility of using that function with anything that is a const.
      -->
      <para>
	Si pasa o retorna una dirección (ya sea un puntero o una
	referencia), el programador cliente puede recoger y modificar
	el valor al que apunta. Si hace que el puntero o referencia
	sea constante, impedirá que esto suceda, lo que puede
	ahorrarle problemas. De hecho, cada vez que se pasa una
	dirección como parámetro a una función, debería hacerla
	constante siempre que sea posible. Si no lo hace, está
	excluyendo la posibilidad de usar la función con constantes.
      </para>

      <!--
      The choice of whether to return a pointer or reference to a const
      depends on what you want to allow your client programmer to do with
      it. Here's an example that demonstrates the use of const pointers as
      function arguments and return values:
      -->
      <para>
	La opción de devolver un puntero o referencia constante
	depende de lo que quiera permitir hacer al programador
	cliente. Aquí se muestra un ejemplo que demuestra el uso de
	punteros constantes como argumentos de funciones y valores de
	retorno.
      </para>



//: V1C08:ConstPointer.cpp



      <!-- [PAG:371] -->
      <!--
      The function t( ) takes an ordinary non-const pointer as an argument,
      and u( ) takes a const pointer. Inside u( ) you can see that
      attempting to modify the destination of the const pointer is illegal,
      but you can of course copy the information out into a non-const
      variable. The compiler also prevents you from creating a non-const
      pointer using the address stored inside a const pointer.
      -->
      <para>
	La función <function>t()</function> toma un puntero no-constante
	ordinario como argumento, y <function>u()</function> toma un
	puntero constante. En el cuerpo de <function>u()</function>
	puede ver un intento de modificar el valor de un puntero
	constante, algo incorrecto, pero puede copiar su valor en una
	variable no constante. El compilador también impide crear un
	puntero no constante y almacenar en él la dirección contenida en
	un puntero constante.
      </para>

      <!--
      The functions v( ) and w( ) test return value semantics. v( ) returns
      a const char* that is created from a character array literal. This
      statement actually produces the address of the character array
      literal, after the compiler creates it and stores it in the static
      storage area. As mentioned earlier, this character array is
      technically a constant, which is properly expressed by the return
      value of v( ).
      -->
      <para>
	Las funciones <function>v()</function> y
	<function>w()</function> prueban las semánticas de retorno de
	valores. <function>v()</function> devuelve un <type>const
	char*</type> que se crea a partir de un literal de
	cadena. Esta sentencia en realidad genera la dirección del
	literal una vez que el compilador lo crea y almacena en área
	de almacenamiento estática. Como se ha dicho antes,
	técnicamente este vector de caracteres es una constante, como
	bien indica el tipo de retorno de <function>v()</function>.
      </para>

      <!--
      The return value of w( ) requires that both the pointer and what it
      points to must be const. As with v( ), the value returned by w( ) is
      valid after the function returns only because it is static. You never
      want to return pointers to local stack variables because they will be
      invalid after the function returns and the stack is cleaned
      up. (Another common pointer you might return is the address of storage
      allocated on the heap, which is still valid after the function
      returns.)
      -->
      <para>
	El valor de retorno de <function>w()</function> requiere que
	tanto el puntero como lo que apunta sean constantes. Como en
	<function>v()</function>, el valor devuelto por
	<function>w()</function> es valido una vez terminada la
	función solo porque es estático. Nunca debe devolver un
	puntero a una variable local pues se almacenan en la pila y al
	terminar la función los datos de la pila desaparecen. Lo que
	si puede hacer es devolver punteros que apuntan a datos
	almacenados en el montón
	(<foreignphrase>heap</foreignphrase>), pues siguen siendo
	validos después de terminar la función.
      </para>


      <!--
      In main( ), the functions are tested with various arguments. You can
      see that t( ) will accept a non-const pointer argument, but if you try
      to pass it a pointer to a const, there's no promise that t( ) will
      leave the pointer's destination alone, so the compiler gives you an
      error message. u( ) takes a const pointer, so it will accept both
      types of arguments. Thus, a function that takes a const pointer is
      more general than one that does not.
      -->
      <para>
	En <function>main()</function> se prueban las funciones con
	varios argumentos. Puede ver que <function>t()</function>
	aceptará como argumento un puntero ordinario, pero si
	intenta pasarle un puntero a una constante, no hay garantía
	de que no vaya a modificarse el valor de la variable
	apuntada; por ello el compilador lo indica con un mensaje de
	error. <function>u()</function> toma un puntero a constante,
	así que puede aceptar los dos tipos de argumentos. Por eso
	una función que acepta un puntero a constante es más general
	que una que acepta un puntero ordinario.
      </para>

      <!--
      As expected, the return value of v( ) can be assigned only to a
      pointer to a const. You would also expect that the compiler refuses to
      assign the return value of w( ) to a non-const pointer, and accepts a
      const int* const, but it might be a bit surprising to see that it also
      accepts a const int*, which is not an exact match to the return
      type. Once again, because the value (which is the address contained in
      the pointer) is being copied, the promise that the original variable
      is untouched is automatically kept. Thus, the second const in const
      int* const is only meaningful when you try to use it as an lvalue, in
      which case the compiler prevents you.
      -->
      <para>
	Como es lógico, el valor de retorno de
	<function>v()</function> sólo se puede asignar a un puntero a
	constante. También era de esperar que el compilador rehuse
	asignar el valor devuelto por <function>w()</function> a un
	puntero ordinario, y que sí acepte un <type>const int*
	const</type>, pero podría sorprender un poco que también
	acepta un <type>const int*</type>, que no es exactamente el
	tipo de retorno declarado en la función. De nuevo, como el
	valor (que es la dirección contenida en el puntero) se copia,
	el requisito de que la variable original permanezca
	inalterable se cumple automáticamente. Por eso, el segundo
	<kw>const</kw> en la declaración <type>const int* const</type>
	sólo se aplica cuando lo use como recipiente, en cuyo caso el
	compilador lo impediría.
      </para>

      <sect3>
        <!-- : Standard argument passing -->
	<title>Criterio de paso de argumentos</title>

      <!--
        In C it's very common to pass by value, and when you want to pass an
        address your only choice is to use a pointer[43]. However, neither of
        these approaches is preferred in C++. Instead, your first choice when
        passing an argument is to pass by reference, and by const reference at
        that. To the client programmer, the syntax is identical to that of
        passing by value, so there's no confusion about pointers - they don't
        even have to think about pointers. For the creator of the function,
        passing an address is virtually always more efficient than passing an
        entire class object, and if you pass by const reference it means your
        function will not change the destination of that address, so the
        effect from the client programmer's point of view is exactly the same
        as pass-by-value (only more efficient).
        -->

	<!--
	Some folks go as far as saying that everything in C is
	pass by value, since when you pass a pointer a copy is made
	(so you're passing the pointer by value). However precise this
	might be, I think it actually confuses the issue.
	-->
	<para>
	  En C es muy común el paso por valor, y cuando se quiere
	  pasar una dirección la única posibilidad es usar un
	  puntero<footnote><para> Algunos autores dicen que todo en C
	  se pasa por valor, ya que cuando se pasa un puntero se hace
	  también una copia (de modo que el puntero se pasa por
	  valor). En cualquier caso, hacer esta precisión puede, en
	  realidad, confundir la cuestión.</para></footnote>. Sin
	  embargo, ninguno de estos modos es el preferido en C++. En
	  su lugar, la primera opción cuando se pasa un parámetro es
	  hacerlo por referencia o mejor aún, por referencia
	  constante. Para el cliente de la función, la sintaxis es
	  idéntica que en el paso por valor, de ese modo no hay
	  confusión posible con los punteros, no hay que pensar en
	  términos de punteros. Para el creador de una función, pasar
	  una dirección es siempre más eficiente que pasar un objeto
	  completo, y si pasa por referencia constante significa que
	  la función no podrá cambiar lo almacenado en esa dirección,
	  así que el efecto desde el punto de vista del programador
	  cliente es lo mismo que el paso por valor (sin embargo es
	  más eficiente).
	</para>

       <!--
        Because of the syntax of references (it looks like pass-by-value to
        the caller) it's possible to pass a temporary object to a function
        that takes a const reference, whereas you can never pass a temporary
        object to a function that takes a pointer - with a pointer, the
        address must be explicitly taken. So passing by reference produces a
        new situation that never occurs in C: a temporary, which is always
        const, can have its address passed to a function. This is why, to
        allow temporaries to be passed to functions by reference, the argument
        must be a const reference. The following example demonstrates this:
        -->
	<para>
	  A causa de la sintaxis de las referencias (para el cliente
	  es igual que el paso por valor) es posible pasar un objeto
	  temporario a una función que toma una referencia constante,
	  mientras que nunca puede pasarse un objeto temporario a una
	  función que toma un puntero (con un puntero, la dirección
	  debe darse explícitamente). Así que con el paso por
	  referencia se produce una nueva situación que nunca ocurre
	  en C: un temporario, que es siempre constante, puede pasar
	  su dirección a una función (una función puede tomar por
	  argumento la dirección de un temporario). Esto es así
	  porque, para permitir que los temporarios se pasen por
	  referencia, el argumento debe ser una referencia
	  constante. El siguiente ejemplo lo demuestra:
	</para>


//: V1C08:ConstTemporary.cpp


        <!--
        f( ) returns an object of class X by value. That means when you
        immediately take the return value of f( ) and pass it to another
        function as in the calls to g1( ) and g2( ), a temporary is created
        and that temporary is const. Thus, the call in g1( ) is an error
        because g1( ) doesn't take a const reference, but the call to g2( ) is
        OK.
        -->
	<para>
	  <function>f()</function> retorna un objeto de la clase
	  <classname>X</classname> por valor. Esto significa que
	  cuando tome el valor de retorno y lo pase inmediatamente a
	  otra función como en las llamadas a
	  <function>g1()</function> y <function>g2()</function>, se
	  crea un temporario y los temporarios son siempre
	  constantes. Por eso, la llamada a <function>g1()</function>
	  es un error pues <function>g1()</function> no acepta una
	  referencia constante, mientras que la llamada a
	  <function>g2()</function> sí es correcta.
	</para>
      </sect3>
    </sect2>
  </sect1>

  <sect1>
    <!-- : Classes -->
    <title>Clases</title>

    <!--
    This section shows the ways you can use const with classes. You may
    want to create a local const in a class to use inside constant
    expressions that will be evaluated at compile time. However, the
    meaning of const is different inside classes, so you must understand
    the options in order to create const data members of a class.
    -->
    <para>
      Esta sección muestra la forma en la que se puede usar el
      especificador <kw>const</kw> con las clases. Puede ser
      interesante crear una constante local a una clase para usarla en
      expresiones constantes que serán evaluadas en tiempo de
      compilación. Sin embargo, el significado del especificador
      <kw>const</kw> es diferente para las clases
      <footnote><para>N. del T.: Esto se conoce como polisemia del
      lenguaje</para></footnote>, de modo que debe comprender las
      opciones adecuadas para crear miembros constantes en una clase.
    </para>

    <!--
    You can also make an entire object const (and as you've just seen, the
    compiler always makes temporary objects const). But preserving the
    constness of an object is more complex. The compiler can ensure the
    constness of a built-in type but it cannot monitor the intricacies of
    a class. To guarantee the constness of a class object, the const
    member function is introduced: only a const member function may be
    called for a const object.
    -->
    <para>
      También se puede hacer que un objeto completo sea constante (y
      como se ha visto, el compilador siempre hace constantes los
      objetos temporarios). Pero preservar la consistencia de un objeto
      constante es más complicado. El compilador puede asegurar la
      consistencia de las variables de los tipos del lenguaje pero no
      puede vigilar la complejidad de una clase. Para garantizar dicha
      consistencia se emplean las funciones miembro constantes; que son
      las únicas que un objeto constante puede invocar.
    </para>
    <!-- [PAG:373] -->

    <sect2>
      <!-- : const in classes -->
      <title><kw>const</kw> en las clases</title>

      <!--
      One of the places you'd like to use a const for constant expressions
      is inside classes. The typical example is when you're creating an
      array inside a class and you want to use a const instead of a #define
      to establish the array size and to use in calculations involving the
      array. The array size is something you'd like to keep hidden inside
      the class, so if you used a name like size, for example, you could use
      that name in another class without a clash. The preprocessor treats
      all #defines as global from the point they are defined, so this will
      not achieve the desired effect.
      -->
      <para>
	Uno de los lugares donde interesa usar <kw>const</kw> es para
	expresiones constantes dentro de las clases. El ejemplo típico
	es cuando se define un vector en una clase y se quiere usar
	<kw>const</kw> en lugar de <kw>#define</kw> para establecer el
	tamaño del vector y para usarlo al calcular datos
	concernientes al vector.  El tamaño del vector es algo que
	desea mantener oculto en la clase, así que si usa un nombre
	como <varname>size</varname>, por ejemplo, se podría usar el
	mismo nombre en otra clase sin que ocurra un conflicto. El
	preprocesador trata todos los <kw>#define</kw> de forma global
	a partir del punto donde se definen, algo que <kw>const</kw>
	permite corregir de forma adecuada consiguiendo el efecto
	deseado.
      </para>

      <!--
      You might assume that the logical choice is to place a const inside
      the class. This doesn't produce the desired result. Inside a class,
      const partially reverts to its meaning in C. It allocates storage
      within each object and represents a value that is initialized once and
      then cannot change. The use of const inside a class means "This is
      constant for the lifetime of the object." However, each different
      object may contain a different value for that constant.
      -->
      <para>
	Se podría pensar que la elección lógica es colocar una
	constante dentro de la clase. Esto no produce el resultado
	esperado. Dentro de una clase <kw>const</kw>
	recupera un poco su significado en C. Asigna espacio de
	almacenamiento para cada variable y representa un valor que
	es inicializado y ya no se puede cambiar. El uso de una
	constante dentro de una clase significa <quote>Esto es constante
	  durante la vida del objeto</quote>. Por otra parte, en cada objeto
	la constante puede contener un valor diferente.
      </para>

      <!--
      Thus, when you create an ordinary (non-static) const inside a class,
      you cannot give it an initial value. This initialization must occur in
      the constructor, of course, but in a special place in the
      constructor. Because a const must be initialized at the point it is
      created, inside the main body of the constructor the const must
      already be initialized. Otherwise you're left with the choice of
      waiting until some point later in the constructor body, which means
      the const would be un-initialized for a while. Also, there would be
      nothing to keep you from changing the value of the const at various
      places in the constructor body.
      -->
      <para>
	Por eso, cuando crea una constante ordinaria (no estática) dentro
	de una clase, no puede darle un valor inicial. Esta inicialización
	debe ocurrir en el constructor. Como la constante se debe
	inicializar en el punto en que se crea, en el cuerpo del
	constructor la constante debe estar ya inicializada. De otro modo,
	le quedaría la opción de esperar hasta algún punto posterior en el
	constructor, lo que significaría que la constante no tendría valor
	por un momento. Y nada impediría cambiar el valor de la constante
	en varios sitios del constructor.
      </para>

      <sect3>
	<!-- : The constructor initializer list -->
	<title>La lista de inicialización del constructor.</title>

        <!--
        The special initialization point is called the constructor initializer
        list, and it was originally developed for use in inheritance (covered
        in Chapter 14). The constructor initializer list - which, as the name
        implies, occurs only in the definition of the constructor - is a list
        of "constructor calls" that occur after the function argument list
        and a colon, but before the opening brace of the constructor
        body. This is to remind you that the initialization in the list occurs
        before any of the main constructor code is executed. This is the place
        to put all const initializations. The proper form for const inside a
        class is shown here:
        -->
	<para>
	  Un punto especial de inicialización es la llamada
	    <quote>lista de inicialización del constructor</quote> y
	    fue pensada en un principio para su uso en herencia
	    (tratada en el [FIXME:XREF:capítulo 14]). La lista de
	    inicialización del constructor (que como su nombre indica,
	    sólo aparece en la definición del constructor) es una
	    lista de llamadas a constructores que aparece después de
	    la lista de argumentos del constructor y antes de abrir la
	    llave del cuerpo del constructor.

          <!-- [PAG:375] -->

	  Se hace así para recordarle que las inicialización de la
	  lista sucede antes de ejecutarse el constructor. Ese es el lugar
	  donde poner las inicializaciones de todas las constantes de la
	  clase. El modo apropiado para colocar las constantes en una clase
	  se muestra a continuación:
	</para>


//: V1C08:ConstInitialization.cpp


        <!--
        The form of the constructor initializer list shown above is confusing
        at first because you're not used to seeing a built-in type treated as
        if it has a constructor.
        -->
	<para>
	  El aspecto de la lista de inicialización del constructor
	  mostrada arriba puede crear confusión al principio porque no
	  es usual tratar los tipos del lenguaje como si tuvieran
	  constructores.
	</para>
      </sect3>

      <sect3>
        <!-- : Constructors for built-in types -->
	<title>Constructores para los tipos del lenguaje</title>

        <!--
        As the language developed and more effort was put into making
        user-defined types look like built-in types, it became apparent that
        there were times when it was helpful to make built-in types look like
        user-defined types. In the constructor initializer list, you can treat
        a built-in type as if it has a constructor, like this:
        -->
	<para>
	  Durante el desarrollo del lenguaje se puso más esfuerzo en
	  hacer que los tipos definidos por el programador se
	  pareciesen a los tipos del lenguaje, pero a veces, cuando
	  se vio útil se hizo que los tipos predefinidos
	  (<foreignphrase>built-in</foreignphrase> se pareciesen a
	  los definidos por el programador. En la lista de
	  inicialización del constructor, puede tratar a los tipos
	  del lenguaje como si tuvieran un constructor, como aquí:
	</para>


//: V1C08:BuiltInTypeConstructors.cpp


	<!-- [PAG:376] -->
        <!--
        This is especially critical when initializing const data members
        because they must be initialized before the function body is entered.
        -->
        <!--
        It made sense to extend this "constructor" for built-in types (which
        simply means assignment) to the general case, which is why the float
        pi(3.14159) definition works in the above code.
        -->
        <!--
        It's often useful to encapsulate a built-in type inside a class to
        guarantee initialization with the constructor. For example, here's an
        Integer class:
        -->
	<para>
	  Esto es especialmente crítico cuando se inicializan
	  atributos constantes porque se deben inicializar antes de
	  entrar en el cuerpo de la función.  Tiene sentido extender
	  este <quote>constructor</quote> para los tipos del lenguaje
	  (que simplemente significan asignación) al caso general que
	  es por lo que la definición <type>float</type> funciona en
	  el código anterior. A menudo es útil encapsular un tipo del
	  lenguaje en una clase para garantizar la inicialización con
	  el constructor. Por ejemplo, aquí hay una clase
	  <classname>Integer</classname>:
	</para>


//: V1C08:EncapsulatingTypes.cpp


        <!--
        The array of Integers in main( ) are all automatically initialized to
        zero. This initialization isn't necessarily more costly than a for
        loop or memset( ). Many compilers easily optimize this to a very fast
        process.
        -->
	<para>
	  El vector de enteros declarado en
	  <function>main()</function> se inicializa automáticamente a
	  cero. Esta inicialización no es necesariamente más costosa
	  que un bucle <kw>for</kw> o
	  <function>memset()</function>. Muchos compiladores lo
	  optimizan fácilmente como un proceso muy rápido.
	</para>
      </sect3>
    </sect2>


<!-- revisando por aquí -->

    <sect2>
      <!-- : Compile-time constants in classes -->
      <title>Constantes en tiempo de compilación dentro de clases</title>

      <!--
      The above use of const is interesting and probably useful in cases,
      but it does not solve the original problem which is: "how do you
      make a compile-time constant inside a class?" The answer requires the
      use of an additional keyword which will not be fully introduced until
      Chapter 10: static. The static keyword, in this situation, means
      "there's only one instance, regardless of how many objects of the
      class are created," which is precisely what we need here: a member
      of a class which is constant, and which cannot change from one object
      of the class to another. Thus, a static const of a built-in type can
      be treated as a compile-time constant.
      -->
      <para>
	El uso anterior de <kw>const</kw> es interesante y
	probablemente útil en muchos casos, pero no resuelve el
	programa original de <quote>cómo hacer una constante en tiempo
	de compilación dentro de una clase</quote>. La respuesta
	requiere del uso de un especificador adicional que se
	explicará completamente en el [FIXME:capítulo 10]:
	<kw>static</kw>. El especificador <kw>static</kw>, en esta
	situación significa <quote>hay sólo una instancia a pesar de
	que se creen varios objetos de la clase</quote> que es
	precisamente lo que se necesita: un atributo de clase que es
	constante, y que no cambia de un objeto a otro de la misma
	clase. Por eso, una <kw>static const</kw> de un tipo básico se
	puede tratar como una constante en tiempo de compilación.
      </para>

      <!--
      There is one feature of static const when used inside classes which is
      a bit unusual: you must provide the initializer at the point of
      definition of the static const. This is something that only occurs
      with the static const; as much as you might like to use it in other
      situations it won't work because all other data members must be
      initialized in the constructor or in other member functions.
      -->
      <para>
	Hay un característica de <kw>static const</kw> cuando se usa
	dentro de clases que es un tanto inusual: se debe indicar el
	valor inicial en el punto en que se define. Esto sólo ocurre
	con <kw>static const</kw> y no funciona en otras situaciones
	porque todos lo otros atributos deben inicializarse en el
	constructor o en otros métodos.
      </para>

      <!--
      Here's an example that shows the creation and use of a static const
      called size inside a class that represents a stack of string
      pointers[44]:
      -->
      <para>
	A continuación aparece un ejemplo que muestra la creación y
	uso de una <kw>static const</kw> llamada
	<varname>size</varname> en una clase que representa una pila
	de punteros a cadenas<footnote><para>Al termino de este libro,
	no todos los compiladores permiten esta
	característica.</para></footnote>.
      </para>



//: V1C08:StringStack.cpp



      <!-- [PAG:379] -->
      <!--
      Since size is used to determine the size of the array stack, it is
      indeed a compile-time constant, but one that is hidden inside the
      class.
      -->
      <para>
	Como <varname>size</varname> se usa para determinar el tamaño
	del vector <varname>stack</varname>, es adecuado usar una
	constante en tiempo de compilación, pero que queda oculta
	dentro de la clase.
      </para>

      <!--
      Notice that push( ) takes a const string* as an argument, pop( )
      returns a const string*, and StringStack holds const string*. If this
      were not true, you couldn't use a StringStack to hold the pointers in
      iceCream. However, it also prevents you from doing anything that will
      change the objects contained by StringStack. Of course, not all
      containers are designed with this restriction.
      -->
      <para>
	Fíjese en que <function>push()</function> toma un <type>const
	string*</type> como argumento, <function>pop()</function>
	retorna un <type>const string*</type> y
	<classname>StringStack</classname> contiene <type>const
	string*</type>. Si no fuera así, no podría usar una
	<classname>StringStack</classname> para contener los punteros
	de <varname>icecream</varname>. En cualquier caso, también
	impide hacer algo que cambie los objetos contenidos en
	<classname>StringStack</classname>. Por supuesto, no todos los
	contenedores están diseñados con esta restricción.
      </para>

      <sect3>
        <!-- : The enum hack in old code -->
	<title>El enumerado en codigo antiguo</title>

	<!--
        In older versions of C++, static const was not supported inside
        classes. This meant that const was useless for constant expressions
        inside classes. However, people still wanted to do this so a typical
        solution (usually referred to as the "enum hack") was to use an
        untagged enum with no instances. An enumeration must have all its
        values established at compile time, it's local to the class, and its
        values are available for constant expressions. Thus, you will commonly
        see:
        -->
	<para>
	  En versiones antiguas de C++ el tipo <kw>static const</kw>
	  no se permitía dentro de las clases. Esto hacía que
	  <kw>const</kw> no pudiese usarse para expresiones constantes
	  dentro de clases. Pero muchos programadores lo conseguían
	  con una solución típica (normalmente conocida como
	  <quote><foreignphrase>enum hack</foreignphrase></quote>) que
	  consiste en usar un <type>enum</type> sin etiqueta y sin
	  instancias. Una enumeración debe tener establecidos sus
	  valores en tiempo de compilación, es local a una clase y sus
	  valores están disponibles para expresiones constantes. Por
	  eso, es habitual ver código como:
	</para>


//: V1C08:EnumHack.cpp


        <!--
        The use of enum here is guaranteed to occupy no storage in the object,
        and the enumerators are all evaluated at compile time. You can also
        explicitly establish the values of the enumerators:
        -->
	<para>
	  Este uso de <type>enum</type> garantiza que no se ocupa
	  almacenamiento en el objeto, y que todos los símbolos
	  definidos en la enumeración se evalúan en tiempo de
	  compilación. Además se puede establecer explícitamente el
	  valor de los símbolos:
	</para>


<programlisting>
enum { one = 1, two = 2, three };
</programlisting>


        <!--
        With integral enum types, the compiler will continue counting from the
        last value, so the enumerator three will get the value 3.
        -->
	<para>
	  utilizando tipos <type>enum</type> enteros, el compilador
	  continuará contando a partir del último valor, así que el
	  símbolo <constant>three</constant> tendrá un valor 3.
	</para>

        <!-- In the StringStack.cpp example above, the line: -->
	<para>
	  En el ejemplo StringStack anterior, la línea:
	</para>


<programlisting>
static const int size = 100;
</programlisting>

        <!-- would be instead: -->
	<para>
	  podriá sustituirse por:
	</para>


<programlisting>
enum { size = 100 };
</programlisting>

        <!--
        Although you'll often see the enum technique in legacy code, the
        static const feature was added to the language to solve just this
        problem. However, there is no overwhelming reason that you must choose
        static const over the enum hack, and in this book the enum hack is
        used because it is supported by more compilers at the time this book
        was written.
        -->
	<para>
	  Aunque es fácil ver esta técnica en código correcto, el uso
	  de <kw>static const</kw> fue añadido al lenguaje
	  precisamente para resolver este problema.  En todo caso, no
	  existe ninguna razón abrumadora por la que deba usar
	  <kw>static const</kw> en lugar de <type>enum</type>, y en
	  este libro se utiliza <type>enum</type> porque hay más
	  compiladores que le dan soporte en el momento en el momento
	  en que se escribió este libro.
	</para>
      </sect3>
    </sect2>

    <sect2>
      <!-- : const objects & member functions -->
      <title>Objetos y métodos constantes</title>

      <!--
      Class member functions can be made const. What does this mean? To
      understand, you must first grasp the concept of const objects.
      -->
      <para>
	Las funciones miembro (métodos) se pueden hacer
	constantes. ¿Qué significa eso? Para entenderlo, primero debe
	comprender el concepto de objeto constante.
      </para>

     <!--
      A const object is defined the same for a user-defined type as a
      built-in type. For example:
      -->
      <para>
	Un objeto constante se define del mismo modo para un tipo
	definido por el usuario que para un tipo del lenguaje. Por
	ejemplo:
      </para>


<programlisting>
const int i = 1;
const blob b(2);
</programlisting>


      <!--
      Here, b is a const object of type blob. Its constructor is called with
      an argument of two. For the compiler to enforce constness, it must
      ensure that no data members of the object are changed during the
      object's lifetime. It can easily ensure that no public data is
      modified, but how is it to know which member functions will change the
      data and which ones are "safe" for a const object?
      -->
      <para>
        Aquí, <varname>b</varname> es un objeto constante de tipo
        <type>blob</type>, su constructor se llama con un
        <literal>2</literal> como argumento. Para que el compilador
        imponga que el objeto sea constante, debe asegurar que el
        objeto no tiene atributos que vayan a cambiar durante el
        tiempo de vida del objeto. Puede asegurar fácilmente que los
        atributos no públicos no sean modificables, pero. ¿Cómo puede
        saber que métodos cambiarán los atributos y cuáles son seguros
        para un objeto constante?
      </para>


      <!--
      If you declare a member function const, you tell the compiler the
      function can be called for a const object. A member function that is
      not specifically declared const is treated as one that will modify
      data members in an object, and the compiler will not allow you to call
      it for a const object.
      -->
      <para>
        Si declara un método como constante, le está diciendo que la
        función puede ser invocada por un objeto constante. Un método
        que no se declara constante se trata como uno que puede
        modificar los atributos del objeto, y el compilador no permitirá
        que un objeto constante lo utilice.
      </para>

      <!--
      It doesn't stop there, however. Just claiming a member function is
      const doesn't guarantee it will act that way, so the compiler forces
      you to reiterate the const specification when defining the
      function. (The const becomes part of the function signature, so both
      the compiler and linker check for constness.) Then it enforces
      constness during the function definition by issuing an error message
      if you try to change any members of the object or call a non-const
      member function. Thus, any member function you declare const is
      guaranteed to behave that way in the definition.
      -->
      <para>
        Pero la cosa no acaba ahí. Sólo porque un método afirme ser
        <kw>const</kw> no garantiza que actuará del modo correcto, de
        modo que el compilador fuerza que en la definición del método
        se reitere el especificador <kw>const</kw> (la palabra
        <kw>const</kw> se convierte en parte del nombre de la función,
        así que tanto el compilador como el enlazador comprobarán que
        no se viole la constancia). De este modo, si durante la
        definición de la función se modifica algún miembro o se llama
        algún método no constante, el compilador emitirá un mensaje de
        error. Por eso, está garantizado que los miembros que declare
        <kw>const</kw> se comportarán del modo esperado.
      </para>

      <!--
      To understand the syntax for declaring const member functions, first
      notice that preceding the function declaration with const means the
      return value is const, so that doesn't produce the desired
      results. Instead, you must place the const specifier after the
      argument list. For example,
      -->
      <para>
	Para comprender la sintaxis para declarar métodos constantes,
	primero debe recordar que colocar <kw>const</kw> delante de la
	declaración del método indica que el valor de retorno es
	constante, así que no produce el efecto deseado. Lo que hay
	que hacer es colocar el especificador <kw>const</kw>
	<emphasis>después</emphasis> de la lista de argumentos. Por
	ejemplo:
      </para>



//: V1C08:ConstMember.cpp



      <!-- [PAG:382] -->
      <!--
      Note that the const keyword must be repeated in the definition or the
      compiler sees it as a different function. Since f( ) is a const member
      function, if it attempts to change i in any way or to call another
      member function that is not const, the compiler flags it as an error.
      -->
      <para>
	La palabra <kw>const</kw> debe incluirse tanto en la
	declaración como en la definición del método o de otro modo el
	compilador asumirá que es un método diferente. Como
	<function>f()</function> es un método constante, si intenta
	modificar <varname>i</varname> de alguna forma o llamar a otro
	método que no sea constante, el compilador informará de un
	error.
      </para>

      <!--
      You can see that a const member function is safe to call with both
      const and non-const objects. Thus, you could think of it as the most
      general form of a member function (and because of this, it is
      unfortunate that member functions do not automatically default to
      const). Any function that doesn't modify member data should be
      declared as const, so it can be used with const objects.
      -->
      <para>
	Puede ver que un miembro constante puede llamarse tanto desde
	objetos constantes como desde no constantes de forma
	segura. Por ello, debe saber que esa es la forma más general
	para un método (a causa de esto, el hecho de que los métodos
	no sean <kw>const</kw> por defecto resulta desafortunado). Un
	método que no modifica ningún atributo se debería escribir
	como constante y así se podría usar desde objetos constantes.
      </para>

      <!--
      Here's an example that contrasts a const and non-const member
      function:-->
      <para>
	Aquí se muestra un ejemplo que compara métodos const y
	métodos ordinarios:
      </para>


//: V1C08:Quoter.cpp


      <!--
      Neither constructors nor destructors can be const member functions
      because they virtually always perform some modification on the object
      during initialization and cleanup. The quote( ) member function also
      cannot be const because it modifies the data member lastquote (see the
      return statement). However, lastQuote( ) makes no modifications, and
      so it can be const and can be safely called for the const object cq.
      mutable:
      -->
      <para>
	Ni los constructores ni los destructores pueden ser métodos
	constantes porque prácticamente siempre realizan alguna
	modificación en el objeto durante la inicialización o la
	terminación. El miembro <function>quote()</function> tampoco
	puede ser constante porque modifica el atributo
	<varname>lastquote</varname> (ver la sentencia de retorno).  Por
	otra parte <function>lastQuote()</function> no hace
	modificaciones y por eso puede ser <kw>const</kw> y
	puede ser llamado de forma segura por el objeto constante
	<varname>cq</varname>.
      </para>

      <sect3>
        <!-- : bitwise vs. logical const -->
	<title>mutable: constancia binaria vs. lógica</title>

        <!--
        What if you want to create a const member function, but you'd still
        like to change some of the data in the object? This is sometimes
        referred to as the difference between bitwise const and logical const
        (also sometimes called memberwise const). Bitwise const means that
        every bit in the object is permanent, so a bit image of the object
        will never change. Logical const means that, although the entire
        object is conceptually constant, there may be changes on a
        member-by-member basis. However, if the compiler is told that an
        object is const, it will jealously guard that object to ensure bitwise
        constness. To effect logical constness, there are two ways to change a
        data member from within a const member function.
        -->
	<para>
	  ¿Qué ocurre si quiere crear un método constante, pero
	  necesita cambiar algún atributo del objeto? Esto se aplica a
	  veces a la diferencia entre constante binaria
	  (<foreignphrase>bitwise</foreignphrase>) y constante lógica
	  (llamado también constante
	  <foreignphrase>memberwise</foreignphrase>). Constante
	  binaria significa que todos los bits del objeto son
	  permanentes, así que la imagen binaria del objeto nunca
	  cambia.  Constante lógica significa que, aunque el objeto
	  completo es conceptualmente constante puede haber cambios a
	  nivel de miembro.  Si se informa al compilador que un objeto
	  es constante, cuidará celosamente el objeto para asegurar
	  constancia binaria. Para conseguir constancia lógica, hay
	  dos formas de cambiar los atributos con un método constante.
	</para>

        <!--
        The first approach is the historical one and is called casting away
        constness. It is performed in a rather odd fashion. You take this (the
        keyword that produces the address of the current object) and cast it
        to a pointer to an object of the current type. It would seem that this
        is already such a pointer. However, inside a const member function
        it's actually a const pointer, so by casting it to an ordinary
        pointer, you remove the constness for that operation. Here's an
        example:
        -->
	<para>
	  La primera solución es la tradicional y se llama constancia
	  <foreignphrase>casting away</foreignphrase>.  Esto se hace
	  de un modo bastante raro. Se toma <varname>this</varname>
	  (la palabra que inidica la dirección del objeto actual) y se
	  moldea el puntero a un puntero a objeto de la clase
	  actual. Parece que <varname>this</varname> ya es un puntero
	  válido. Sin embargo, dentro de un método constante,
	  <varname>this</varname> es en realidad un puntero constante,
	  así que moldeándolo a un puntero ordinario se elimina la
	  constancia del objeto para esta operación. Aquí hay un
	  ejemplo:
	</para>


//: V1C08:Castaway.cpp


        <!--
        This approach works and you'll see it used in legacy code, but it is
        not the preferred technique. The problem is that this lack of
        constness is hidden away in a member function definition, and you have
        no clue from the class interface that the data of the object is
        actually being modified unless you have access to the source code (and
        you must suspect that constness is being cast away, and look for the
        cast). To put everything out in the open, you should use the mutable
        keyword in the class declaration to specify that a particular data
        member may be changed inside a const object:
        -->
	<para>
	  Esta aproximación funciona y puede verse en código
	  correcto, pero no es la técnica ideal. El problema es que
	  esta falta de constancia está oculta en la definición de
	  un método y no hay ningún indicio en la interfaz de la
	  clase que haga sospechar que ese dato se modifica a menos
	  que puede accederse al código fuente (buscando el
	  molde). Para poner todo al descubierto se debe usar la
	  palabra <kw>mutable</kw> en la declaración de la
	  clase para indicar que un atributo determinado se puede
	  cambiar aún perteneciendo a un objeto constante.
	</para>


//: V1C08:Mutable.cpp


        <!--
        This way, the user of the class can see from the declaration which
        members are likely to be modified in a const member function.
        -->
	<para>
	  De este modo el usuario de la clase puede ver en la declaración
	  qué miembros tienen posibilidad de ser modificados por un método.
	</para>
      </sect3>
      <sect3>
        <!-- : ROMability -->
        <title>ROMability</title>


	<!-- [PAG:386] -->
        <!--
        If an object is defined as const, it is a candidate to be placed in
        read-only memory (ROM), which is often an important consideration in
        embedded systems programming. Simply making an object const, however,
        is not enough - the requirements for ROMability are much stricter. Of
        course, the object must be bitwise-const, rather than
        logical-const. This is easy to see if logical constness is implemented
        only through the mutable keyword, but probably not detectable by the
        compiler if constness is cast away inside a const member function. In
        addition,
        -->
	<para>
	  Si un objeto se define como constante es un candidato para
	  ser almacenado en memoria de sólo lectura (ROM), que a
	  menudo es una consideración importante en programación de
	  sistemas empotrados. Para conseguirlo no es suficiente con
	  que el objeto sea constante, los requisitos son mucha más
	  estrictos. Por supuesto, el objeto debe ser una constante
	  binaria. Eso es fácil de comprobar si la constancia lógica
	  se implementa mediante el uso de <kw>mutable</kw>, pero
	  probablemente el compilador no podrá detectarlo si se
	  utiliza la técnica del moldeado dentro de un método
	  constante. Además:
	</para>


	<itemizedlist>
	  <listitem>
        <!--
        1. The class or struct must have no user-defined constructors or
        destructor.
        -->
	    <para>
	      La clase o estructura no puede tener constructores o destructor
	      definidos por el usuario.
	    </para>
	  </listitem>
	  <listitem>
        <!--
        2. There can be no base classes (covered in Chapter 14) or member
        objects with user-defined constructors or destructors.
        -->
	    <para>
	      No pueden ser clases base (capitulo 14) u objetos
	      miembro con constructores o destructor definidos por el
	      usuario.
	    </para>
	  </listitem>
	</itemizedlist>

        <!--
        The effect of a write operation on any part of a const object of a
        ROMable type is undefined. Although a suitably formed object may be
        placed in ROM, no objects are ever required to be placed in ROM.
        -->
	<para>
	  El efecto de una operación de escritura en una parte del
	  objeto constante de un tipo <type>ROMable</type> no está
	  definido. Aunque un objeto pueda ser colocado en ROM de
	  forma conveniente, no todos lo requieren.
	</para>
      </sect3>
    </sect2>
  </sect1>

  <sect1>
    <!-- : volatile -->
    <title>Volatile</title>

    <!--
    The syntax of volatile is identical to that for const, but volatile
    means "This data may change outside the knowledge of the
    compiler." Somehow, the environment is changing the data (possibly
    through multitasking, multithreading or interrupts), and volatile
    tells the compiler not to make any assumptions about that data,
    especially during optimization.
    -->
    <para>
      La sintaxis de <kw>volatile</kw> es idéntica a la de
      <kw>const</kw>, pero <kw>volatile</kw> significa <quote>este
      dato puede cambiar sin que el compilador sea informado de
      ello</quote>. De algún modo, el entorno modifica el dato
      (posiblemente mediante multitarea, multihilo o interrupciones),
      y <kw>volatile</kw> indica la compilador que no haga
      suposiciones sobre el dato, especialmente durante la
      optimización.
    </para>


    <!--
    If the compiler says, "I read this data into a register earlier, and I
    haven't touched that register," normally it wouldn't need to read
    the data again. But if the data is volatile, the compiler cannot make
    such an assumption because the data may have been changed by another
    process, and it must reread that data rather than optimizing the code
    to remove what would normally be a redundant read.
    -->
    <para>
      Si el compilador dice, <quote>yo guardé este dato en un registro
      anteriormente, y no he tocado ese registro</quote>, normalmente
      no necesitará leer el dato de nuevo desde memoria. Pero si esa
      variable es <kw>volatile</kw>, el compilador no debe hacer esa
      suposición porque el dato puede haber cambiado a causa de otro
      proceso, y debe releer el dato en vez de optimizar el código
      (dicha optimización consiste en eliminar la lectura redundante
      que se hace normalmente).
    </para>

    <!--
    You create volatile objects using the same syntax that you use to
    create const objects. You can also create const volatile objects,
    which can't be changed by the client programmer but instead change
    through some outside agency. Here is an example that might represent a
    class associated with some piece of communication hardware:
    -->
    <para>
      Pueden crearse objetos <kw>volatile</kw> usando la misma
      sintaxis que se usa para crear objetos constantes. También puede
      crearse objetos <kw>volatile</kw> constantes que no pueden
      cambiarse por el programador cliente pero se pueden modificar
      por una entidad ajena al programa. Aquí se muestra un ejemplo
      que representa una clase asociada con algún elemento físico de
      comunicación.
    </para>


//: V1C08:Volatile.cpp


    <!-- [PAG:388] -->
    <!--
    As with const, you can use volatile for data members, member
    functions, and objects themselves. You can only call volatile member
    functions for volatile objects.
    -->
    <para>
      Como ocurre con <kw>const</kw>, se puede usar <kw>volatile</kw>
      para los atributos de la clase, los métodos y para los objetos
      en sí mismos. Sólo puede llamar a métodos <kw>volatile</kw>
      desde objetos <kw>volatile</kw>.
    </para>

    <!--
    The reason that isr( ) can't actually be used as an interrupt service
    routine is that in a member function, the address of the current
    object (this) must be secretly passed, and an ISR generally wants no
    arguments at all. To solve this problem, you can make isr( ) a static
    member function, a subject covered in Chapter 10.
    -->
    <para>
      La razón por la que <function>isr()</function> no se puede usar
      como una rutina de servicio de interrupción (ISR) es que en un
      método, la dirección del objeto actual (<varname>this</varname>)
      debe pasarse secretamente, y una ISR no requiere
      argumentos. Para resolver este problema se puede hacer que el
      método <function>isr()</function> sea un método de clase
      (<kw>static</kw>), un asunto que se trata en el [FIXME:capitulo
      10].
    </para>

    <!--
    The syntax of volatile is identical to const, so discussions of the
    two are often treated together. The two are referred to in combination
    as the c-v qualifier.
    -->
    <para>
      La sintaxis de <kw>volatile</kw> es idéntica a la de
      <kw>const</kw>, así que por eso se suelen tratar juntos. Cuando
      se usan combinados se conocen como cuantificador
      <emphasis>c-v</emphasis> (const-volatile).
    </para>
  </sect1>



  <sect1>
    <!-- : Summary -->
    <title>Resumen</title>

    <!--
    The const keyword gives you the ability to define objects, function
    arguments, return values and member functions as constants, and to
    eliminate the preprocessor for value substitution without losing any
    preprocessor benefits. All this provides a significant additional form
    of type checking and safety in your programming. The use of so-called
    const correctness (the use of const anywhere you possibly can) can be
    a lifesaver for projects.
    -->
    <para>
      La palabra <kw>const</kw> permite la posibilidad de definir
      objetos, argumentos de función, valores de retorno y métodos
      como constantes y elimina el uso del preprocesador para la
      sustitución de valores sin perder ninguna de sus ventajas. Todo
      ello ofrece una forma adicional de comprobación de tipos y
      seguridad en la programación. El uso de la llamada
      <quote>constancia exacta</quote> (<foreignphrase>const
      correctness</foreignphrase>) es decir, el uso de <kw>const</kw>
      en todo lugar donde sea posible, puede ser un salvavidas para
      muchos proyectos.
    </para>

    <!--
    Although you can ignore const and continue to use old C coding
    practices, it's there to help you. Chapters 11 and on begin using
    references heavily, and there you'll see even more about how critical
    it is to use const with function arguments.
    -->
    <para>
      Aunque ignore a <kw>const</kw> y continue usando el estilo
      tradicional de C, <kw>const</kw> existe para ayudarle. El
      [FIXME:capitulo 11] utiliza las referencias extensamente, y se
      verá más sobre la importancia del uso de <kw>const</kw> en los
      argumentos de funciones.
    </para>
  </sect1>

  <sect1>
    <title>Ejercicios</title>

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

    <orderedlist>
      <listitem>
	<!--
	1. Create three const int values, then add them together to produce
	a value that determines the size of an array in an array
	definition. Try to compile the same code in C and see what happens
	(you can generally force your C++ compiler to run as a C compiler
	by using a command-line flag).
	-->
	<para>
	  Cree 3 valores enteros constantes, después súmelos todos
	  para producir un valor que determine el tamaño en la
	  definición de un vector. Intente compilar el mismo código
	  en C y vea qué sucede (generalmente se puede forzar al
	  compilador de C++ para que funcione como un compilador de
	  C utilizando alguna opción de linea de comandos).
	</para>
      </listitem>
      <listitem>
	<!--
	2. Prove to yourself that the C and C++ compilers really do treat
	constants differently. Create a global const and use it in a global
	constant expression; then compile it under both C and C++.
	-->
	<para>
	  Probar que los compiladores de C y C++ realmente tratan las
	  constantes de modo diferente. Cree una constante global y
	  úsela en una expresión global constante, compile dicho
	  código en C y C++.
	</para>
      </listitem>
      <listitem>
	<!--
	3. Create example const definitions for all the built-in types and
	their variants. Use these in expressions with other consts to make
	new const definitions. Make sure they compile successfully.
	-->
	<para>
	  Cree definiciones constantes para todos los tipos del
	  lenguaje y sus variantes. Úselos en expresiones con otras
	  constantes para hacer definiciones de constantes
	  nuevas. Compruebe que compilan correctamente.
	</para>
      </listitem>
      <listitem>
	<!--
	4. Create a const definition in a header file, include that header
	file in two .cpp files, then compile those files and link them. You
	should not get any errors. Now try the same experiment with C.
	-->
	<para>
	  Cree una definición de constante en un archivo de cabecera,
	  incluya dicho archivo en dos archivos
	  <filename>.cpp</filename>, compílelos y enlácelos con el
	  compilador de C++. No deberían ocurrir errores. Ahora
	  intente el mismo experimento con el compilador de C.
	</para>
      </listitem>
      <listitem>
	<!--
	5. Create a const whose value is determined at runtime by reading
	the time when the program starts (you'll have to use the <ctime>
	standard header). Later in the program, try to read a second value
	of the time into your const and see what happens.
	-->
	<para>
	  Cree una constante cuyo valor se determine en tiempo de
	  ejecución leyendo la hora en que comienza la ejecución del
	  programa (puede usar <filename
	    class="headerfile">&lt;ctime&gt;</filename>). Después, en el
	  programa, intente leer un segundo valor de hora,
	  almacenarlo en la constante y vea qué sucede.
	</para>
      </listitem>
      <listitem>
	<!--
	6. Create a const array of char, then try to change one of the
	chars.
	-->
	<para>
	  Cree un vector de caracteres constante, después intente
	  cambiar uno de los caracteres.
	</para>
      </listitem>
      <listitem>
	<!--
	7. Create an extern const declaration in one file, and put a main(
	) in that file that prints the value of the extern const. Provide
	an extern const definition in a second file, then compile and link
	the two files together.
	-->
	<para>
	  Cree una declaración de constante <kw>extern</kw> en un
	  fichero y ponga un <function>main()</function> en el que se
	  imprima el valor de dicha constante. Cree una definición de
	  constante <kw>extern</kw> en un segundo fichero, compile y
	  enlace los dos ficheros.
	</para>
      </listitem>
      <listitem>
	<!--
	8. Write two pointers to const long using both forms of the
	declaration. Point one of them to an array of long. Demonstrate
	that you can increment or decrement the pointer, but you can't
	change what it points to.
	-->
	<para>
	  Defina dos punteros a <type>const long</type> utilizando
	  las dos formas de definición. Apunte con uno de ellos a
	  un vector de <type>long</type>. Demuestre que se puede
	  incrementar o decrementar el puntero, pero no se puede
	  cambiar el valor de lo que apunta.
	</para>
      </listitem>
      <listitem>
	<!--
	9. Write a const pointer to a double, and point it at an array of
	double. Show that you can change what the pointer points to, but
	you can't increment or decrement the pointer.
	-->
	<para>
	  Defina un puntero constante a <type>double</type>, y apunte
	  con él a un vector de <type>double</type>. Demuestre que se
	  puede cambiar lo que apunta el puntero pero no se puede
	  incrementar ni decrementar el puntero.
	</para>
	<!-- [PAG:390] -->
      </listitem>
      <listitem>
	<!--
	10. Write a const pointer to a const object. Show that you can only
	read the value that the pointer points to, but you can't change the
	pointer or what it points to.
	-->
	<para>
	  Defina un puntero constante a objeto constante. Pruebe que
	  solamente se puede leer el valor de lo que apunta el puntero,
	  pero no se puede cambiar el puntero ni lo que apunta.
	</para>
      </listitem>
      <listitem>
	<!--
	11. Remove the comment on the error-generating line of code in
	PointerAssignment.cpp to see the error that your compiler generates.
	-->
	<para>
	  Elimine el comentario de la linea errónea en
	  <filename>PointerAssignemt.cpp</filename> para ver qué
	  mensaje de error muestra el compilador.
	</para>
      </listitem>
      <listitem>
	<!--
	12. Create a character array literal with a pointer that points to
	the beginning of the array. Now use the pointer to modify elements
	in the array. Does your compiler report this as an error? Should it?
	If it doesn't, why do you think that is?
	-->
	<para>
	  Cree un literal de cadena y un puntero que apunte al
	  comienzo del literal. Ahora, use el puntero para
	  modificar los elementos del vector, ¿Informa el compilador
	  de algún error? ¿Debería? Si no lo hace, ¿Porqué piensa
	  que puede ser?
	</para>
      </listitem>
      <listitem>
	<!--
	13. Create a function that takes an argument by value as a const;
	then try to change that argument in the function body.
	-->
	<para>
	  Cree una función que tome un argumento por valor como constante,
	  después intente cambiar el argumento en el cuerpo de la
	  función.
	</para>
      </listitem>
      <listitem>
	<!--
	14. Create a function that takes a float by value. Inside the
	function, bind a const float& to the argument, and only use the
	reference from then on to ensure that the argument is not changed.
	-->
	<para>
	  Cree una función que tome un <type>float</type> por
	  valor. Dentro de la función vincule el argumento a un
	  <type>const float&amp;</type> y use dicha referencia para
	  asegurar que el argumento no sea modificado
	</para>
      </listitem>
      <listitem>
	<!--
	15. Modify ConstReturnValues.cpp removing comments on the
	error-causing lines one at a time, to see what error messages your
	compiler generates.
	-->
	<para>
	  Modifique <filename>ConstReturnValues.cpp</filename>
	  eliminando los comentarios en las líneas erróneas una cada
	  vez para ver qué mensajes de error muestra el compilador.
	</para>
      </listitem>
      <listitem>
	<!--
	16. Modify ConstPointer.cpp removing comments on the error-causing
	lines one at a time, to see what error messages your compiler
	generates.
	-->
	<para>
	  Modifique <filename>ConsPointer.cpp</filename> eliminando
	  los comentarios en las líneas erróneas para ver qué mensajes
	  de error muestra el compilador.
	</para>
      </listitem>
      <listitem>
	<!--
	17. Make a new version of ConstPointer.cpp called ConstReference.cpp
	which demonstrates references instead of pointers (you may need to
	look forward to Chapter 11).
	-->
	<para>
	  Haga una nueva versión de
	  <filename>ConstPointer.cpp</filename> llamada
	  <filename>ConstReference.cpp</filename> que demuestre el
	  funcionamiento con referencias en lugar de con punteros.
	  (quizá necesite consultar el [FIXME:capítulo 11]).
	</para>
      </listitem>
      <listitem>
	<!--
	18. Modify ConstTemporary.cpp removing the comment on the
	error-causing line to see what error messages your compiler
	generates.
	-->
	<para>
	  Modifique <filename>ConstTemporary.cpp</filename>
	  eliminando el comentario en la línea errónea para ver el
	  mensaje de error que muestra el compilador.
	</para>
      </listitem>
      <listitem>
	<!--
	19. Create a class containing both a const and a non-const
	float. Initialize these using the constructor initializer list.
	-->
	<para>
	  Cree una clase que contenga un <type>float</type> constante
	  y otro no constante. Inicialícelos usando la lista de
	  inicialización del constructor.
	  <!-- [PAG:391] -->
	</para>
      </listitem>
      <listitem>
	<!--
	20. Create a class called MyString which contains a string and has a
	constructor that initializes the string, and a print( )
	function. Modify StringStack.cpp so that the container holds
	MyString objects, and main( ) so it prints them.
	-->
	<para>
	  Cree una clase llamada <classname>MyString</classname>
	  que contenga una cadena y tenga un constructor que
	  inicialice la cadena y un método
	  <function>print()</function>. Modifique
	  <filename>StringStack.cpp</filename> para que maneje
	  objetos <classname>MyString</classname> y
	  <function>main()</function> para que los imprima.
	</para>
      </listitem>
      <listitem>
	<!--
	21. Create a class containing a const member that you initialize in
	the constructor initializer list and an untagged enumeration that
	you use to determine an array size.
	-->
	<para>
	  Cree una clase que contenga un atributo constante que se
	  inicialice en la lista de inicialización del constructor y
	  una enumeración no etiquetada que se use para determinar
	  el tamaño de un vector.
	</para>
      </listitem>
      <listitem>
	<!--
	22. In ConstMember.cpp, remove the const specifier on the member
	function definition, but leave it on the declaration, to see what
	kind of compiler error message you get.
	-->
	<para>
	  Elimine el especificador <kw>const</kw> en la definición del
	  método de <filename>ConstMember.cpp</filename>, pero deje
	  el de la declaración para ver qué mensaje de error muestra
	  el compilador.
	</para>
      </listitem>
      <listitem>
	<!--
	23. Create a class with both const and non-const member
	functions. Create const and non-const objects of this class, and try
	calling the different types of member functions for the different
	types of objects.
	-->
	<para>
	  Cree una clase con un método constante y otro
	  ordinario. Cree un objeto constante y otro no constante de
	  esa clase e intente invocar ambos métodos desde ambos
	  objetos.
	</para>
      </listitem>
      <listitem>
	<!--
	24. Create a class with both const and non-const member
	functions. Try to call a non-const member function from a const
	member function to see what kind of compiler error message you get.
	-->
	<para>
	  Cree una clase con un método constante y otro
	  ordinario. Intente llamar al método ordinario desde el
	  método constante para ver qué mensaje de error muestra el
	  compilador.
	</para>
      </listitem>
      <listitem>
	<!--
	25. In Mutable.cpp, remove the comment on the error-causing line to
	see what sort of error message your compiler produces.
	-->
	<para>
	  Elimine el comentario de la línea errónea en
	  <filename>mutable.cpp</filename> para ver el mensaje de
	  error que muestra el compilador.
	</para>
      </listitem>
      <listitem>
	<!--
	26. Modify Quoter.cpp by making quote( ) a const member function and
	lastquote mutable.
	-->
	<para>
	  Modifique <filename>Quoter.cpp</filename> haciendo que
	  <function>quote()</function> sea un método constante y
	  <varname>lastquote</varname> sea <kw>mutable</kw>.
	</para>
      </listitem>
      <listitem>
	<!--
	27. Create a class with a volatile data member. Create both volatile
	and non-volatile member functions that modify the volatile data
	member, and see what the compiler says. Create both volatile and
	non-volatile objects of your class and try calling both the volatile
	and non-volatile member functions to see what is successful and what
	kind of error messages the compiler produces.
	-->
	<para>
	  Cree una clase con un atributo <kw>volatile</kw>. Cree
	  métodos <kw>volatile</kw> y no <kw>volatile</kw> que
	  modifiquen el atributo <kw>volatile</kw> y vea qué dice el
	  compilador.  Cree objetos <kw>volatile</kw> y no
	  <kw>volatile</kw> de esa clase e intente llamar a ambos
	  métodos para comprobar si funciona correctamente y ver qué
	  mensajes de error muestra el compilador en caso contrario.
	</para>
      </listitem>
      <listitem>
	<!--
	Create a class called bird that can fly( ) and a class
	rock that can't. Create a rock object, take its address, and
	assign that to a void*. Now take the void*, assign it to a
	bird* (you'll have to use a cast), and call fly( ) through
	that pointer. Is it clear why C's permission to openly assign
	via a void* (without a cast) is a 'hole' in the language,
	which couldn't be propagated into C++?  -->
	<para>
	  Cree una clase llamada <classname>bird</classname> que
	  pueda ejecutar <function>fly()</function> y una clase
	  <classname>rock</classname> que no pueda. Crear un objeto
	  <varname>rock</varname>, tome su dirección y asigne a un
	  <type>void*</type>. Ahora tome el <type>void*</type>,
	  asígnelo a un <type>bird*</type> (debe usar un molde) y
	  llame a <function>fly()</function> a través de dicho
	  puntero. ¿Esto es posible porque la característica de C que
	  permite asignar a un <type>void*</type> (sin un molde) es
	  un agujero del lenguaje, que no debería propagarse a C++?
	</para>
      </listitem>
    </orderedlist>
  </sect1>
</chapter>


<!--
- Local variables:
-   ispell-local-dictionary: "castellano8"
- End:
-->
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.