Source

PensarEnC++ / V1-C10.xml

The branch 'PensarEnC++' does not exist.
Full commit
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
<?xml  version="1.0" encoding="utf-8"?>
<!-- -*- sgml -*- -->
<!--
  Editor:              Emacs 21/PSGML
  Traducción original: josemaria.gomez@gmail.com
  Formateado DocBook:  David Villa <dvilla@gmx.net>
  1ª Revisión:         David Villa <dvilla@gmx.net>
  2ª Revisión
-->

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

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

  <title>Control de nombres</title>

  <!--
  Creating names is a fundamental activity in programming, and when a
  project gets large, the number of names can easily be overwhelming.
  -->

  <highlights>
    <para>
      La creación de nombres es una actividad fundamental en la
      programación, y cuando un proyecto empieza a crecer, el número
      de nombres puede llegar a ser inmanejable con facilidad.
    </para>
  </highlights>

  <!--
  C++ allows you a great deal of control over the creation and
  visibility of names, where storage for those names is placed, and
  linkage for names. The static keyword was overloaded in C before
  people knew what the term "overload" meant, and C++ has added yet
  another meaning. The underlying concept with all uses of static seems
  to be "something that holds its position" (like static electricity),
  whether that means a physical location in memory or visibility within
  a file.
  -->


  <para>
    C++ <function>permite</function> gran control sobre la creación y visibilidad de
    nombres, el lugar donde se almacenan y el enlazado de nombres. La
    palabra clave <kw>static</kw> estaba sobrecargada en C incluso
    antes de que la mayoría de la gente supiera que significaba el
    término <quote>sobrecargar</quote>. C++ ha añadido además otro
    significado. El concepto subyacente bajo todos los usos de
    <kw>static</kw> parece ser <quote>algo que mantiene su
    posición</quote> (como la electricidad estática), sea manteniendo
    un ubicación física en la memoria o su visibilidad en un fichero.
  </para>

  <!--
  In this chapter, you'll learn how static controls storage and
  visibility, and an improved way to control access to names vía C++'s
  namespace feature. You'll also find out how to use functions that were
  written and compiled in C.
  -->

  <para>
    En este capítulo aprenderá cómo <kw>static</kw> controla el
    almacenamiento y la visibilidad, así como una forma mejorada para
    controlar los nombres mediante el uso de la palabra clave de C++
    <kw>namespace</kw>. También descubrirá como utilizar funciones que
    fueron escritas y compiladas en C.
  </para>

  <sect1>
    <title>Los elementos estáticos de C</title>

    <!--
    In both C and C++ the keyword static has two basic meanings,
    which unfortunately often step on each other's toes:
    -->

    <para>
      Tanto en C como en C++ la palabra clave <kw>static</kw> tiene dos
      significados básicos que, desafortunadamente, a menudo se confunden:
    </para>


    <itemizedlist>
      <listitem>
	<!--
	1. Allocated once at a fixed address; that is, the object is
	created in a special static data área rather than on the stack each
	time a function is called. This is the concept of static storage.
	-->
	<para>
	  Almacenado una sola vez en una dirección de memoria fija. Es
	  decir, el objeto se crea en una área de datos estática
	  especial en lugar de en la pila cada vez que se llama a una
	  función. Éste es el concepto de almacenamiento estático.
	</para>
      </listitem>
      <listitem>
	<!--
	2. Local to a particular translation unit (and local to a class
	scope in C++, as you will see later).  Here, static
	controls the visibility of a name, so that name cannot
	be seen outside the translation unit or class. This also
	describes the concept of linkage, which determines what
	names the linker will see.
	-->
	<para>
	  Local a una unidad de traducción particular (y también local
	  para el ámbito de una clase en C++, tal como se verá
	  después). Aquí, <kw>static</kw> controla la visibilidad de
	  un nombre, de forma que dicho nombre no puede ser visto
	  fuera del la unidad de traducción o la clase. Esto también
	  corresponde al concepto de enlazado, que determina qué
	  nombres verá el enlazador.
	</para>
      </listitem>
    </itemizedlist>

    <para>
      En esta sección se van a analizar los significados anteriores de
      <kw>static</kw> tal y como se heredaron de C.
    </para>

    <sect2>
      <title>Variables estáticas dentro de funciones</title>

      <!--
      When you create a local variable inside a function, the compiler
      allocates storage for that variable each time the function is
      called by moving the stack pointer down an appropriate amount. If
      there is an initializer for the variable, the initialization is
      performed each time that sequence point
      -->

      <para>
	Cuando se crea una variable local dentro de una función, el
	compilador reserva espacio para esa variable cada vez que se
	llama a la función moviendo hacia abajo el puntero de pila tanto
	como sea preciso. Si existe un inicializador para la variable,
	la inicialización se realiza cada vez que se pasa por ese punto
	de la secuencia.
      </para>

      <!--
      Sometimes, however, you want to retain a value between function
      calls. You could accomplish this by making a global variable, but
      then that variable would not be under the sole control of the
      function. C and C++ allow you to create a static object inside a
      function; the storage for this object is not on the stack but
      instead in the program's static data area. This object is
      initialized only once, the first time the function is called, and
      then retains its value between function invocations. For example,
      the following function returns the next character in the array
      each time the function is
      -->


      <para>
	No obstante, a veces es deseable retener un valor entre llamadas
	a función. Esto se puede lograr creando una variable global,
	pero entonces esta variable no estará únicamente bajo control de
	la función. C y C++ permiten crear un objeto <kw>static</kw> dentro de
	una función. El almacenamiento de este objeto no se lleva a cabo
	en la pila sino en el área de datos estáticos del
	programa. Dicho objeto sólo se inicializa una vez, la primera
	vez que se llama a la función, y retiene su valor entre
	diferentes invocaciones. Por ejemplo, la siguiente función
	devuelve el siguiente carácter del vector cada vez que se la
	llama:
      </para>



//: V1C10:StaticVariablesInfunctions.cpp



      <!--
      The static char* s holds its value between calls of oneChar( )
      because its storage is not part of the stack frame of the
      function, but is in the static storage área of the program. When
      you call oneChar( ) with a char* argument, s is assigned to that
      argument, and the first character of the array is returned. Each
      subsequent call to oneChar( ) without an argument produces the
      default value of zero for charArray, which indicates to the
      function that you are still extracting characters from the
      previously initialized value of s. The function will continúe to
      produce characters until it reaches the null terminator of the
      character array, at which point it stops incrementing the pointer
      so it doesn't overrun the end of the array.
      -->

      <para>
	La variable <type>static char* s</type> mantiene su valor
	entre llamadas a <function>oneChar()</function> porque no está
	almacenada en el segmento de pila de la función, sino que está
	en el área de almacenamiento estático del programa. Cuando se
	llama a <function>oneChar()</function> con <type>char*</type>
	como argumento, <varname>s</varname> se asigna a ese argumento
	de forma que se devuelve el primer carácter del array. Cada
	llamada posterior a <function>oneChar()</function>
	<emphasis>sin</emphasis> argumentos devuelve el valor por
	defecto cero para <varname>charArray</varname>, que indica a
	la función que todavía se están extrayendo caracteres del
	valor previo de <varname>s</varname>. La función continuará
	devolviendo caracteres hasta que alcance el valor de final del
	vector, momento en el que para de incrementar el puntero
	evitando que éste sobrepase la última posición del vector.
      </para>


      <!--
      But what happens if you call oneChar( ) with no arguments and
      without previously initializing the value of s?  In the definition
      for s, you could have provided an initializer, <sect3>
      -->

      <para>
	Pero ¿qué pasa si se llama a <function>oneChar()</function>
	sin argumentos y sin haber inicializado previamente el valor
	de <varname>s</varname>? En la definición para
	<varname>s</varname>, se podía haber utilizado la
	inicialización,
      </para>

      <programlisting>
      static char* s = 0;
      </programlisting>

      <!--
      but if you do not provide an initializer for a static
      variable of a built-in type, the compiler guarantees that variable
      will be initialized to zero (converted to the proper type) at
      program start-up. So in oneChar( ), the first time the function is
      called, s is zero. In this case, the if(!s) conditional will catch
      it.  -->

      <para>
	pero si no se incluye un valor inicial para una variable
	estática de un tipo definido, el compilador garantiza que la
	variable se inicializará a cero (convertido al tipo adecuado)
	al comenzar el programa. Así pues, en
	<function>oneChar()</function>, la primera vez que se llama a
	la función, <varname>s</varname> vale cero.  En este caso, se
	cumplirá la condición <code>if(!s)</code>.
      </para>

      <!--
	The initialization above for s is very simple, but
	initialization for static objects (like all other objects) can
	be arbitrary expressions involving constants and previously
	declared variables and functions.
      -->

      <para>
	La inicialización anterior para <varname>s</varname> es muy
	simple, pero la inicialización para objetos estáticos (como la
	de cualquier otro objeto) puede ser una expresión arbitraria,
	que involucre constantes, variables o funciones previamente
	declaradas.
      </para>


      <!--
	You should be aware that the function above is very vulnerable
	to multithreading problems; whenever you design functions
	containing static variables you should keep multithreading
	issues in mind.
      -->


      <para>
	Fíjese que la función de arriba es muy vulnerable a problemas de
	concurrencia. Siempre que diseñe funciones que contengan
	variables estáticas, deberá tener en mente este tipo de
	problemas.
      </para>

      <sect3>
	<title>Objetos estáticos dentro de funciones</title>

	<!--
	The rules are the same for static objects of user-defined types,
	including the fact that some initialization is required for the
	object. However, assignment to zero has meaning only for
	built-in types; user-defined types must be initialized with
	constructor calls. Thus, if you don't specify constructor
	arguments when you define the static object, the class must have
	a default constructor. For example,
	-->

	<para>
	  Las reglas son las mismas para objetos estáticos de tipos
	  definidos por el usuario, añadiendo el hecho que el objeto
	  requiere ser inicializado. Sin embargo, la asignación del
	  valor cero sólo tiene sentido para tipos predefinidos. Los
	  tipos definidos por el usuario deben ser inicializados
	  llamando a sus respectivos constructores.  Por tanto, si no
	  especifica argumentos en los constructores cuando defina un
	  objeto estático, la clase deberá tener un constructor por
	  defecto. Por ejemplo:
	</para>



//: V1C10:StaticObjectsInFunctions.cpp



	<!--
	  The static objects of type X inside f( ) can be initialized
	  either with the constructor argument list or with the default
	  constructor. This construction occurs the first time control
	  passes through the definition, and only the first time.
	  -->

	<para>
	  Los objetos estáticos de tipo <type>X</type> dentro de
	  <function>f()</function> pueden ser inicializados tanto con
	  la lista de argumentos del constructor como con el
	  constructor por defecto. Esta construcción ocurre únicamente
	  la primera vez que el control llega a la definición.
	</para>
      </sect3>



      <sect3>
	<title>Destructores de objetos estáticos</title>

	<!--
	Destructors for static objects (that is, all objects with static
	storage, not just local static objects as in the example above)
	are called when main( ) exits or when the Standard C library
	function exit( ) is explicitly called. In most implementations,
	main( ) just calls exit( ) when it terminates. This means that
	it can be dangerous to call exit( ) inside a destructor because
	you can end up with infinite recursion. Static object
	destructors are not called if you exit the program using the
	Standard C library function abort( ).  -->

	<para>
	  Los destructores para objetos estáticos (es decir, cualquier
	  objeto con almacenamiento estático, no sólo objetos
	  estáticos locales como en el ejemplo anterior) son invocados
	  cuando <function>main()</function> finaliza o cuando la
	  función de librería estándar de C
	  <function>exit()</function> se llama explícitamente. En la
	  mayoría de implementaciones, <function>main()</function>
	  simplemente llama a <function>exit()</function> cuando
	  termina. Esto significa que puede ser peligroso llamar a
	  <function>exit()</function> dentro de un destructor porque
	  podría producirse una invocación recursiva infinita. Los
	  destructores de objetos estáticos no se invocan si se sale
	  del programa utilizando la función de librería estándar de C
	  <function>abort()</function>.
	</para>

	<!--
	You can specify actions to take place when leaving main( ) (or
	calling exit( )) by using the Standard C library function
	atexit( ). In this case, the functions registered by atexit( )
	may be called before the destructors for any objects constructed
	before leaving main( ) (or calling exit( )).  -->

	<para>
	  Es posible especificar acciones que se lleven a cabo tras
	  finalizar la ejecución de <function>main()</function> (o
	  llamando a <function>exit()</function>) utilizando la
	  función de librería estándar de C
	  <function>atexit()</function>. En este caso, las funciones
	  registradas en <function>atexit()</function> serán invocadas
	  antes de los destructores para cualquier objeto construido
	  antes de abandonar <function>main()</function> (o de llamar
	  a <function>exit()</function>).
	</para>

	<!--
	Like ordinary destruction, destruction of static objects occurs in
	the reverse order of initialization. However, only objects that
	have been constructed are destroyed. Fortunately, the C++
	development tools keep track of initialization order and the
	objects that have been constructed.  Global objects are always
	constructed before main( ) is entered and destroyed as main( )
	exits, but if a function containing a local static object is
	never called, the constructor for that object is never executed,
	so the destructor is also not executed. For example, -->

	<para>
	  Como la destrucción ordinaria, la destrucción de objetos
	  estáticos se lleva a cabo en orden inverso al de la
	  inicialización. Hay que tener en cuenta que sólo los objetos
	  que han sido construidos serán destruidos.  Afortunadamente,
	  las herramientas de desarrollo de C++ mantienen un registro
	  del orden de inicialización y de los objetos que han sido
	  construidos. Los objetos globales siempre se construyen
	  antes de entrar en <function>main()</function> y se
	  destruyen una vez se sale, pero si existe una función que
	  contiene un objeto local estático a la que nunca se llama,
	  el constructor de dicho objeto nunca fue ejecutado y, por
	  tanto, nunca se invocará su destructor. Por ejemplo:
	</para>



//: V1C10:StaticDestructors.cpp



	<!--
	In Obj, the char c acts as an identifier so the constructor and
	destructor can print out information about the object they're
	working on. The Obj a is a global object, so the constructor is
	always called for it before main( ) is entered, but the
	constructors for the static Obj b inside f( ) and the static Obj
	c inside g( ) are called only if those functions are called.
	-->

	<para>
	  En <classname>Obj</classname>, <code>char c</code> actúa
	  como un identificador de forma que el constructor y el
	  destructor pueden imprimir la información acerca del objeto
	  sobre el que actúan. <code>Obj a</code> es un objeto global
	  y por tanto su constructor siempre se llama antes de que el
	  control pase a <function>main()</function>, pero el
	  constructor para <code>static Obj b</code> dentro de
	  <function>f()</function>, y el de <code>static Obj c</code>
	  dentro de <function>g()</function> sólo serán invocados si
	  se llama a esas funciones.
	</para>


	<!--
	To demonstrate which constructors and destructors are called,
	only f( ) is called. The output of the program is -->

	<para>
	  Para mostrar qué constructores y qué destructores serán
	  llamados, sólo se invoca a <function>f()</function>. La
	  salida del programa será la siguiente:
	</para>

<screen>
Obj::Obj() for a
inside main()
Obj::Obj() for b
leaving main()
Obj::~Obj() for b
Obj::~Obj() for a
</screen>

	<!--
	The constructor for a is called before main( ) is entered, and the
	constructor for b is called only because f( ) is called. When
	main( ) exits, the destructors for the objects that have been
	constructed are called in reverse order of their
	construction. This means that if g( ) is called, the order in
	which the destructors for b and c are called depends on whether
	f( ) or g( ) is called first.  -->

	<para>
	  El constructor para <varname>a</varname> se invoca antes de
	  entrar en <function>main()</function> y el constructor de
	  <varname>b</varname> se invoca sólo porque existe una
	  llamada a <function>f()</function>. Cuando se sale de
	  <function>main()</function>, se invoca a los destructores de
	  los objetos que han sido construidos en orden inverso al de
	  su construcción. Esto significa que si llama a
	  <function>g()</function>, el orden en el que los
	  destructores para <varname>b</varname> y
	  <varname>c</varname> son invocados depende de si se llamó
	  primero a <function>f()</function> o a
	  <function>g()</function>.
	</para>


	<!--
	Notice that the trace file ofstream object out is also a static
	object - since it is defined outside of all functions, it
	lives in the static storage area. It is important that its
	definition (as opposed to an extern declaration) appear at the
	beginning of the file, before there is any possible use of
	out. Otherwise, you'll be using an object before it is properly
	initialized.  -->

	<para>
	  Nótese que el objeto <varname>out</varname> de tipo
	  <varname>ofstream</varname>, utilizado en la gestión de
	  ficheros, también es un objeto estático (puesto que está
	  definido fuera de cualquier función, reside en el área de
	  almacenamiento estático). Es importante remarcar que su
	  definición (a diferencia de una declaración tipo
	  <kw>extern</kw>) aparece al principio del fichero, antes de
	  cualquier posible uso de <varname>out</varname>.  De lo
	  contrario estaríamos utilizando un objeto antes de que
	  estuviese adecuadamente inicializado.
	</para>

	<!--
	In C++, the constructor for a global static object is called
	before main( ) is entered, so you now have a simple and portable
	way to execute code before entering main( ) and to execute code
	with the destructor after exiting main( ). In C, this was always
	a trial that required you to root around in the compiler
	vendor's assembly-language startup code.  -->

	<para>
	  En C++, el constructor de un objeto estático global se
	  invoca antes de entrar en <function>main()</function>, de
	  forma que ya dispone de una forma simple y portable de
	  ejecutar código antes de entrar en
	  <function>main()</function>, así como ejecutar código
	  después de salir de <function>main()</function>. En C, eso
	  siempre implicaba revolver el código ensamblador de arranque
	  del compilador utilizado.
	</para>

      </sect3>
    </sect2>

    <sect2>
      <title>Control del enlazado</title>

      <!--
      Ordinarily, any name at file scope (that is, not nested
      inside a class or function) is visible throughout all translation
      units in a program. This is often called <kw>extern</kw>al linkage because
      at link time the name is visible to the linker everywhere,
      <kw>extern</kw>al to that translation unit. Global variables and ordinary
      functions have <kw>extern</kw>al linkage.  -->

      <para>
	Generalmente, cualquier nombre dentro del ámbito del fichero
	(es decir, no incluido dentro de una clase o de una función)
	es visible para todas las unidades de traducción del
	programa. Esto suele llamarse enlazado
	externo<emphasis></emphasis> porque durante el enlazado ese
	nombre es visible desde cualquier sitio, desde el exterior de
	esa unidad de traducción. Las variables globales y las
	funciones ordinarias tienen enlazado externo.
      </para>

	<!--
	There are times when you'd like to limit the visibility of
	a name. You might like to have a variable at file scope so all
	the functions in that file can use it, but you don't want
	functions outside that file to see or access that variable, or
	to inadvertently cause name clashes with identifiers outside the
	file.
	-->

      <para>
	Hay veces en las que conviene limitar la visibilidad de un
	nombre. Puede que desee tener una variable con visibilidad a
	nivel de fichero de forma que todas las funciones de ese
	fichero puedan utilizarla, pero quizá no desee que funciones
	externas a ese fichero tengan acceso a esa variable, o que de
	forma inadvertida, cause solapes de nombres con
	identificadores externos a ese fichero.
      </para>

      <!--
      An object or function name at file scope that is explicitly
      declared static is local to its translation unit (in the terms
      of this book, the cpp file where the declaration occurs). That
      name has internal linkage. This means that you can use the same
      name in other translation units without a name clash.  -->

      <para>
	Un objeto o nombre de función, con visibilidad dentro del
	fichero en que se encuentra, que es explícitamente declarado
	como <kw>static</kw> es local a su unidad de traducción (en
	términos de este libro, el fichero <filename>cpp</filename>
	donde se lleva a cabo la declaración). Este nombre tiene
	<emphasis>enlace interno</emphasis>. Esto significa que puede
	usar el mismo nombre en otras unidades de traducción sin
	confusión entre ellos.
      </para>

      <!--
      One advantage to internal linkage is that the name can be placed
      in a header file without worrying that there will be a clash at
      link time. Names that are commonly placed in header files, such
      as const definitions and inline functions, default to internal
      linkage. (However, const defaults to internal linkage only in
      C++; in C it defaults to external linkage.) Note that linkage
      refers only to elements that have addresses at link/load time;
      thus, class declarations and local variables have no linkage.
      -->

      <para>
	Una ventaja del enlace interno es que el nombre puede situarse
	en un fichero de cabecera sin tener que preocuparse de si
	habrá o no un choque de nombres durante el enlazado. Los
	nombres que aparecen usualmente en los archivos de cabecera,
	como definiciones <kw>const</kw> y funciones <kw>inline</kw>,
	tienen por defecto enlazado interno. (De todas formas,
	<kw>const</kw> tiene por defecto enlazado interno sólo en C++;
	en C tiene enlazado externo). Nótese que el enlazado se
	refiere sólo a elementos que tienen direcciones en tiempo de
	enlazado / carga. Por tanto, las declaraciones de clases y de
	variables locales no tienen enlazado.
      </para>

      <sect3>
	<title>Confusión</title>

	<!--
	Here's an example of how the two meanings of static can
	cross over each other. All global objects implicitly have static
	storage class, so if you say (at file scope), -->

	<para>
	  He aquí un ejemplo de cómo los dos significados de
	  <kw>static</kw> pueden confundirse. Todos los objetos
	  globales tienen implícitamente almacenamiento de tipo
	  estático, o sea que si usted dice (en ámbito de fichero)
	</para>

	<programlisting>
	  int a = 0;
	</programlisting>

	<!--
	then storage for a will be in the program's static data area,
	and the initialization for a will occur once, before main( ) is
	entered. In addition, the visibility of a is global across all
	translation units. In terms of visibility, the opposite of
	static (visible only in this translation unit) is <kw>extern</kw>, which
	explicitly states that the visibility of the name is across all
	translation units. So the definition above is equivalent to
	saying
	-->

	<para>
	  el almacenamiento para <varname>a</varname> se llevará a
	  cabo en el área para datos estáticos del programa y la
	  inicialización para <varname>a</varname> sólo se realizará
	  una vez, antes de entrar en
	  <function>main()</function>. Además, la visibilidad de
	  <varname>a</varname> es global para todas las unidades de
	  traducción. En términos de visibilidad, lo opuesto a
	  <kw>static</kw> (visible tan sólo en su :unidad de
	  traducción) es <kw>extern</kw> que establece explícitamente
	  que la visibilidad del nombre se extienda a todas las
	  unidades de traducción.  Es decir, la definición de arriba
	  equivale a
	</para>

	<programlisting>
	extern int a = 0;
	</programlisting>

	<!--
	But if you say instead,
	-->

	<para>
	  Pero si utilizase
	</para>

	<programlisting>
	  static int a = 0;
	</programlisting>

	<!--
	all you've done is change the visibility, so a has internal
	linkage. The storage class is unchanged - the object resides
	in the static data area whether the visibility is static or
	extern.
	-->

	<para>
	  todo lo que habría hecho es cambiar la visibilidad, de forma
	  que <varname>a</varname> tiene enlace interno. El tipo de
	  almacenamiento no se altera, el objeto reside en el área de
	  datos estática aunque en este caso su visibilidad es
	  <kw>static</kw> y en el otro es <kw>extern</kw>.
	</para>

	<!--
	Once you get into local variables, static stops altering the
	visibility and instead alters the storage class.
	-->

	<para>
	  Cuando pasamos a hablar de variables locales,
	  <kw>static</kw> deja de alterar la visibilidad y pasa a
	  alterar el tipo de almacenamiento.
	</para>


	<!--
	If you declare what appears to be a local variable as
	extern, it means that the storage exists elsewhere (so the
	variable is actually global to the function). For example:
	-->

	<para>
	  Si declara lo que parece ser una variable local como
	  <kw>extern</kw>, significa que el almacenamiento existe en
	  alguna otra parte (y por tanto la variable realmente es
	  global a la función). Por ejemplo:
	</para>


//: V1C10:LocalExtern.cpp



	<!--
	With function names (for non-member functions), static and
	extern can only alter visibility, so if you say -->

	<para>
	  Para nombres de funciones (sin tener en cuenta las funciones
	  miembro), <kw>static</kw> y <kw>extern</kw> sólo pueden
	  alterar la visibilidad, de forma que si escribe
	</para>

	<programlisting>
	  extern void f();
	</programlisting>

	<!--
	it's the same as the unadorned declaration
	-->

	<para>
	  es lo mismo que la menos adornada declaración
	</para>

	<programlisting>
	  void f();
	</programlisting>

	<!--
	and if you say,
	-->

	<para>
	  y si utiliza
	</para>

	<programlisting>
	  static void f();
	</programlisting>

	<!--
	it means f( ) is visible only within this translation unit
	- this is sometimes called file static.
	-->

	<para>
	  significa que <function>f()</function> es visible sólo para
	  la unidad de traducción, (esto suele llamarse <emphasis>estático a
	  fichero</emphasis> (<foreignphrase>file static</foreignphrase>).
	</para>

      </sect3>
    </sect2>

    <sect2>
      <title>Otros especificadores para almacenamiento de clases</title>

      <!--
      You will see static and extern used commonly. There are two other
      storage class specifiers that occur less often. The auto specifier
      is almost never used because it tells the compiler that this is a
      local variable. auto is short for "automatic" and it refers
      to the way the compiler automatically allocates storage for the
      variable. The compiler can always determine this fact from the
      context in which the variable is defined, so auto is redundant.
      -->

      <para>
      	El uso de <kw>static</kw> y <kw>extern</kw> está muy
      	extendido. Existen otros dos especificadores de tipo de
      	almacenamiento bastante menos conocidos. El especificador
      	<kw>auto</kw> no se utiliza prácticamente nunca porque le dice
	  al compilador que esa es una variable local. <kw>auto</kw> es
      	la abreviatura de automático<quote></quote> y se refiere a la
      	forma en la que el compilador reserva espacio automáticamente
      	para la variable. El compilador siempre puede determinar ese
      	hecho por el contexto en que la variable se define por lo que
	<kw>auto</kw> es redundante.
      </para>

      <!--
      A register variable is a local (auto) variable, along with a hint
      to the compiler that this particular variable will be heavily used
      so the compiler ought to keep it in a register if it can. Thus, it
      is an optimization aid. Various compilers respond differently to
      this hint; they have the option to ignore it. If you take the
      address of the variable, the register specifier will almost
      certainly be ignored. You should avoid using register because the
      compiler can usually do a better job of optimization than you.
      -->

      <para>
	El especificador <kw>register</kw> aplicado a una variable
      	indica que es una variable local (<kw>auto</kw>), junto con la
      	pista para el compilador de que esa variable en concreto va a
      	ser ampliamente utilizada por lo que debería ser almacenada en
      	un registro si es posible. Por tanto, es una ayuda para la
      	optimización. Diferentes compiladores responden de diferente
      	manera ante dicha pista; incluso tienen la opción de
      	ignorarla. Si toma la dirección de la variable, el
      	especificador <kw>register</kw> va a ser ignorado casi con
      	total seguridad. Se recomienda evitar el uso de
      	<kw>register</kw> porque, generalmente, el compilador suele
      	realizar las labores de optimización mejor que el usuario.
      </para>

    </sect2>
  </sect1>

  <sect1>
    <title>Espacios de nombres</title>

    <!-- Although names can be nested inside classes, the names of
    global functions, global variables, and classes are still in a
    single global name space. The static keyword gives you some control
    over this by allowing you to give variables and functions internal
    linkage (that is, to make them file static). But in a large project,
    lack of control over the global name space can cause problems.  To
    solve these problems for classes, vendors often create long
    complicated names that are unlikely to clash, but then you're stuck
    typing those names. (A typedef is often used to simplify this.) It's
    not an elegant, language-supported solution.  -->

    <para>
      Pese a que los nombres pueden estar anidados dentro de clases,
      los nombres de funciones globales, variables globales y clases
      se encuentran incluidos dentro de un único espacio de
      nombres. La palabra reservada <kw>static</kw> le da control
      sobre éste permitiéndole darle tanto a variables como a
      funciones enlazado interno (es decir convirtiéndolas en
      estáticas al fichero).  Pero en un proyecto grande, la falta de
      control sobre el espacio de nombres global puede causar
      problemas. Con el fin de solventar esos problemas para clases,
      los programadores suelen crear nombres largos y complicados que
      tienen baja probabilidad de crear conflictos pero que suponen
      hartarse a teclear para escribirlos. (Para simplificar este
      problema se suele utilizar <kw>typedef</kw>). Pese a que el
      lenguaje la soporta, no es una solución elegante.
    </para>

    <!-- You can subdivide the global name space into more manageable
    pieces using the namespace feature of C++. The namespace keyword,
    similar to class, struct, enum, and union, puts the names of its
    members in a distinct space. While the other keywords have
    additional purposes, the creation of a new name space is the only
    purpose for namespace.  -->

    <para>
      En lugar de eso puede subdividir el espacio de nombres global en
      varias partes más manejables utilizando la característica
      <kw>namespace</kw> de C++. La palabra reservada
      <kw>namespace</kw>, de forma similar a <kw>class</kw>,
      <kw>struct</kw>, <kw>enum</kw> y <kw>union</kw>, sitúa los
      nombres de sus miembros en un espacio diferente. Mientras que
      las demás palabras reservadas tienen propósitos adicionales, la
      única función de <kw>namespace</kw> es la de crear un nuevo
      espacio de nombres.
    </para>

    <sect2>
      <title>Crear un espacio de nombres</title>
      <!--
      The creation of a namespace is notably similar to the creation of a class:
      -->

      <para>
	La creación de un espacio de nombres es muy similar a la
	creación de una clase:
      </para>


//: V1C10:MyLib.cpp



      <!-- This produces a new namespace containing the enclosed
      declarations. There are significant differences from class,
      struct, union and enum, however:

      * A namespace definition can appear only at global scope, or
        nested within another namespace.
      * No terminating semicolon is necessary after the closing brace
        of a namespace definition.
      * A namespace definition can be "continúed" over multiple header
        files using a syntax that,
      for a class, would appear to be a redefinition:
      -->

      <para>
	Ese código crea un nuevo espacio de nombres que contiene las
	declaraciones incluidas entre las llaves. De todas formas,
	existen diferencias significativas entre <kw>class</kw>,
	<kw>struct</kw>, <kw>enum</kw> y <kw>union</kw>:
      </para>

  <itemizedlist>
	<listitem>
	  <para>
	    Una definición con namespace solamente puede aparecer en
	    un rango global de visibilidad o anidado dentro de otro
	    namespace.
	  </para>
	</listitem>
	<listitem>
	   <para>
	    No es necesario un punto y coma tras la llave de cierre
      para finalizar la definición de namespace.
    </para>
    </listitem>
  <listitem>
	<para>
	  Una definición namespace puede ser "continuada" en
	  múltiples archivos de cabecera utilizando una sintaxis
	  que, para una clase, parecería ser la de una
	  redefinición:
	  </para>
      </listitem>
    </itemizedlist>



//: V1C10:Header1.h



      <!--
      A namespace name can be aliased to another name, so you don't
      have to type an unwieldy name created by a library vendor: -->

      <para>
	El posible crear alias de un <kw>namespace</kw> de forma que
	no hace falta que teclee un enrevesado nombre creado por algún
	frabricante de librerías:
      </para>



//: V1C10:BobsSuperDuperLibrary.cpp



      <!--
      You cannot create an instance of a namespace as you can with a class.
      -->

      <para>
	No puede crear una instancia de un <kw>namespace</kw> tal y
	como puede hacer con una clase.
      </para>


      <sect3>
	<!-- Unnamed namespaces -->
	<title>Espacios de nombres sin nombre</title>

	<!--
	Each translation unit contains an unnamed namespace that
	you can add to by saying "namespace" without an
	identifier: -->

	<para>
	  Cada unidad de traducción contiene un espacio de nombres sin
	  nombre al que puede referirse escribiendo
	  <quote><code>namespace</code></quote> sin ningún
	  identificador.
	</para>

	<!-- The names in this space are automatically available in that
	translation unit without qualification.  It is guaranteed that
	an unnamed space is unique for each translation unit. If you put
	local names in an unnamed namespace, you don't need to give them
	internal linkage by making them static.

	C++ deprecates the use of file statics in favor of the unnamed namespace.
	-->

	<para>
	  Los nombres en este espacio están disponibles
	  automáticamente en esa unidad de traducción sin
	  cualificación. Se garantiza que un espacio sin nombre es
	  único para cada unidad de traducción. Si usted asigna
	  nombres locales en un espacio de nombres no necesitará
	  darles enlazado interno con <kw>static</kw>.
	</para>

	<para>
	  En C++ es preferible utilizar espacios de nombres sin nombre
	  que <emphasis>estáticos a fichero</emphasis>.
	</para>
      </sect3>

      <sect3>
	<!-- Friends -->
	<title>Amigas</title>

	<!-- You can inject a friend declaration into a namespace by
	declaring it within an enclosed class: -->

	<para>
	  Es posible añadir una declaración tipo <kw>friend</kw>
	  dentro de un espacio de nombres incluyéndola dentro de una
	  clase:
	</para>



//: V1C10:FriendInjection.cpp



	<!-- Now the function you( ) is a member of the namespace Me.

	If you introduce a friend within a class in the global
	namespace, the friend is injected globally.  -->

	<para>
	  Ahora la función <function>you()</function> es un miembro
	  del espacio de nombres <varname>Me</varname>.
	</para>

	<para>
	  Si introduce una declaración tipo <kw>friend</kw> en una
	  clase dentro del espacio de nombres global, dicha
	  declaración se inyecta globalmente.
	</para>
      </sect3>
    </sect2>

    <sect2>
      <title>Cómo usar un espacio de nombres</title>

      <!--You can refer to a name within a namespace in three ways: by
      specifying the name using the scope resolution operator, with a
      using directive to introduce all names in the namespace, or with a
      using declaration to introduce names one at a time.-->

      <para>
	Puede referirse a un nombre dentro de un espacio de nombres de
	tres maneras diferentes: especificando el nombre utilizando el
	operador de resolución de ámbito, con una directiva
	<kw>using</kw> que introduzca todos los nombres en el espacio
	de nombres o mediante una declaración <kw>using</kw> para
	introducir nombres de uno en uno.
      </para>

      <sect3>
	<title>Resolución del ámbito</title>

	<!--Any name in a namespace can be explicitly specified using
	the scope resolution operator in the same way that you can refer
	to the names within a class: -->

	<para>
	  Cualquier nombre en un espacio de nombres puede ser
	  explícitamente especificado utilizando el operador de resolución
	  de ámbito de la misma forma que puede referirse a los nombres
	  dentro de una clase:
	</para>



//: V1C10:ScopeResolution.cpp



	<!-- Notice that the definition X::Y::i could just as
	easily be referring to a data member of a class Y nested in a
	class X instead of a namespace X.

	So far, namespaces look very much like classes.-->

	<para>
	  Nótese que la definición <code>X::Y::i</code> puede
	  referirse también a un atributo de la clase
	  <classname>Y</classname> anidada dentro de la clase
	  <classname>X</classname> en lugar del espacio de nombres
	  <varname>X</varname>.
	</para>
      </sect3>

      <sect3>
	<title>La directiva <kw>using</kw></title>

	<!--Because it can rapidly get tedious to type the full
	qualification for an identifier in a namespace, the using
	keyword allows you to import an entire namespace at once. When
	used in conjunction with the namespace keyword this is called a
	using directive. The using directive makes names appear as if
	they belong to the nearest enclosing namespace scope, so you can
	conveniently use the unqualified names. Consider a simple
	namespace: -->

	<para>
	  Puesto que teclear toda la especificación para un
	  identificador en un espacio de nombres puede resultar
	  rápidamente tedioso, la palabra clave <kw>using</kw> le
	  permite importar un espacio de nombres entero de una vez.
	  Cuando se utiliza en conjunción con la palabra clave
	  <kw>namespace</kw>, se dice que utilizamos una directiva
	  <kw>using</kw><emphasis></emphasis>. Las directivas
	  <kw>using</kw> hacen que los nombres actúen como si
	  perteneciesen al ámbito del espacio de nombres que les
	  incluye más cercano por lo que puede utilizar
	  convenientemente los nombres sin explicitar completamente su
	  especificación. Considere el siguiente espacio de nombres:
	</para>



//: V1C10:NamespaceInt.h



	<!-- One use of the using directive is to bring all of the names
	in Int into another namespace, leaving those names nested within
	the namespace: -->

	<para>
	  Un uso de las directivas <kw>using</kw> es incluir todos los
	  nombres en <varname>Int</varname> dentro de otro espacio de
	  nombres, dejando aquellos nombres anidados dentro del
	  espacio de nombres
	</para>



//: V1C10:NamespaceMath.h



	<!-- You can also declare all of the names in Int inside a
	function, but leave those names nested within the function: -->


	<para>
	  También puede declarar todos los nombres en
	  <varname>Int</varname> dentro de la función pero dejando
	  esos nombres anidados dentro de la función:
	</para>


//: V1C10:Arithmetic.cpp



	<!-- Without the using directive, all the names in the namespace
	would need to be fully qualified.

	One aspect of the using directive may seem slightly
	counterintuitive at first. The visibility of the names
	introduced with a using directive is the scope in which the
	directive is made. But you can override the names from the using
	directive as if they've been declared globally to that scope!
	-->

	<para>
	  Sin la directiva <kw>using</kw>, todos los nombres en el
	  espacio de nombres requerirían estar completamente
	  explicitados.
	</para>

	<para>
	  Hay un aspecto de la directiva <kw>using</kw> que podría
	  parecer poco intuitivo al principio. La visibilidad de los
	  nombres introducidos con una directiva <kw>using</kw> es el
	  rango en el que se crea la directiva. Pero ¡puede hacer caso
	  omiso de los nombres definidos en la directiva
	  <kw>using</kw> como si estos hubiesen sido declarados
	  globalmente para ese ámbito!
	</para>



//: V1C10:NamespaceOverriding1.cpp


	<!-- Suppose you have a second namespace that contains some of
	the names in namespace Math: -->

	<para>
	  Suponga que tiene un segundo espacio de nombres que contiene
	  algunos nombres en <code>namespace Math</code>:
	</para>



//: V1C10:NamespaceOverriding2.h


	<!-- Since this namespace is also introduced with a using
	directive, you have the possibility of a collision. However, the
	ambiguity appears at the point of use of the name, not at the
	using directive: -->

	<para>
	  Dado que este espacio de nombres también se introduce con
	  una directiva <kw>using</kw>, existe la posibilidad de tener
	  una colisión. De todos modos, la ambigüedad aparece en el
	  momento de utilizar el nombre, no en la directiva
	  <kw>using</kw>:
	</para>



//: V1C10:OverridingAmbiguity.cpp


	<!-- Thus, it's possible to write using directives to introduce
	a number of namespaces with conflicting names without ever
	producing an ambiguity.-->

	<para>
	  Por tanto, es posible escribir directivas <kw>using</kw>
	  para introducir un número de espacios de nombre con nombres
	  conflictivos sin producir ninguna ambigüedad.
	</para>
      </sect3>

      <sect3>
	<title>La declaración <kw>using</kw></title>

	<!--You can inject names one at a time into the current scope
	with a using declaration. Unlike the using directive, which
	treats names as if they were declared globally to the scope, a
	using declaration is a declaration within the current
	scope. This means it can override names from a using directive:
	-->

	<para>
	  Puede inyectar nombres de uno en uno en el ámbito actual
	  utilizando una declaración <kw>using</kw>.  A diferencia de
	  la directiva <kw>using</kw>, que trata los nombres como si
	  hubiesen sido declarados globalmente para ese ámbito, una
	  declaración <kw>using</kw> es una declaración dentro del
	  ámbito actual. Eso significa que puede sobrescribir nombres
	  de una directiva <kw>using</kw>:
	</para>


//: V1C10:UsingDeclaration.h


	<!-- The using declaration just gives the fully specified name
	of the identifier, but no type information.  This means that if
	the namespace contains a set of overloaded functions with the
	same name, the using declaration declares all the functions in
	the overloaded set.

	You can put a using declaration anywhere a normal declaration
	can occur. A using declaration works like a normal declaration
	in all ways but one: because you don't give an argument list,
	it's possible for a using declaration to cause the overload of a
	function with the same argument types (which isn't allowed with
	normal overloading). This ambiguity, however, doesn't show up
	until the point of use, rather than the point of declaration.

	A using declaration can also appear within a namespace, and it
	has the same effect as anywhere else - that name is declared
	within the space: -->

	<para>
	  La declaración <kw>using</kw> simplemente da el nombre
	  completamente especificado del identificador pero no da
	  información de tipo. Eso significa que si el espacio de
	  nombres contiene un grupo de funciones sobrecargadas con el
	  mismo nombre, la declaración <kw>using</kw> declara todas
	  las funciones pertenecientes al grupo sobrecargado.
	</para>

	<para>
	  Es posible poner una declaración <kw>using</kw> en cualquier
	  sitio donde podría ponerse una declaración normal.  Una
	  declaración <kw>using</kw> funciona de la misma forma que
	  cualquier declaración normal salvo por un aspecto: puesto
	  que no se le da ninguna lista de argumentos, una declaración
	  <kw>using</kw> puede provocar la sobrecarga de una función
	  con los mismos tipos de argumentos (cosa que no está
	  permitida por el procedimiento de sobrecarga normal). De
	  todas formas, esta ambigüedad no se muestra hasta el momento
	  de uso, no apareciendo en el instante de declaración.
	</para>

	<para>
	  Una declaración <kw>using</kw> puede también aparecer dentro de un
	  espacio de nombres y tiene el mismo efecto que en cualquier otro
	  lugar (ese nombre se declara dentro del espacio):
	</para>


//: V1C10:UsingDeclaration2.cpp


	<!-- A using declaration is an alias, and it allows you to
	declare the same function in separate namespaces. If you end up
	re-declaring the same function by importing different
	namespaces, it's OK - there won't be any ambiguities or
	duplications.-->

	<para>
	  Una declaración <kw>using</kw> es un alias. Le permite declarar la
	  misma función en espacios de nombres diferentes. Si acaba
	  redeclarando la misma función importando diferentes espacios de
	  nombres no hay problema, no habrá ambigüedades o duplicados.
	</para>
      </sect3>
    </sect2>

    <sect2>
      <title>El uso de los espacios de nombres</title>

      <!--Some of the rules above may seem a bit daunting at first,
      especially if you get the impression that you'll be using them all
      the time. In general, however, you can get away with very simple
      usage of namespaces as long as you understand how they work. The
      key thing to remember is that when you introduce a global using
      directive (vía a "using namespace" outside of any scope) you
      have thrown open the namespace for that file. This is usually fine
      for an implementation file (a "cpp" file) because the using
      directive is only in effect until the end of the compilation of
      that file. That is, it doesn't affect any other files, so you can
      adjust the control of the namespaces one implementation file at a
      time. For example, if you discover a name clash because of too
      many using directives in a particular implementation file, it is a
      simple matter to change that file so that it uses explicit
      qualifications or using declarations to eliminate the clash,
      without modifying other implementation files.
      -->

      <para>
	Algunas de las reglas de arriba pueden parecer un poco
	desalentadoras al principio, especialmente si tiene la impresión
	que las utilizará constantemente. No obstante, en general es
	posible salir airoso con el uso de espacios de nombres
	fácilmente siempre y cuando comprenda como funcionan. La clave a
	recordar es que cuando introduce una directiva <kw>using</kw> global (vía
	"using namespace" fuera de cualquier rango) usted ha abierto el
	espacio de nombres para ese archivo. Esto suele estar bien para
	un archivo de implementación (un archivo "cpp") porque la
	directiva <kw>using</kw> sólo afecta hasta el final de la compilación de
	dicho archivo. Es decir, no afecta a ningún otro archivo, de
	forma que puede ajustar el control de los espacios de nombres
	archivo por archivo.  Por ejemplo, si usted descubre un cruce de
	nombres debido a que hay demasiadas directivas <kw>using</kw> en un
	archivo de implementación particular, es una cuestión simple
	cambiar dicho archivo para que use calificaciones explícitas o
	declaraciones <kw>using</kw> para eliminar el cruce sin tener que
	modificar ningún otro archivo de implementación.
      </para>

      <!--
      Header files are a different issue. You virtually never want to
      introduce a global using directive into a header file, because
      that would mean that any other file that included your header
      would also have the namespace thrown open (and header files can
      include other header files).
      -->
      <para>
	Los ficheros de cabecera ya son otra historia. Prácticamente
	nunca querrá introducir una directiva <kw>using</kw> global en
	un fichero de cabecera, puesto que eso significaría que
	cualquier otro archivo que incluyese la cabecera también
	tendría el espacio de nombres desplegado (y un fichero de
	cabecera puede incluir otros ficheros de cabecera).
      </para>


      <!--
      So, in header files you should either use explicit
      qualification or scoped using directives and using
      declarations. This is the practice that you will find in this
      book, and by following it you will not "pollute" the
      global namespace and throw yourself back into the
      pre-namespace world of C++.
      -->
      <para>
	Por tanto, en los ficheros de cabecera debería utilizar o bien
	cualificación explícita o bien directivas <kw>using</kw> de
	ámbito y declaraciones <kw>using</kw>. Éste es el método que
	encontrará en este libro. Siguiendo esta metodología no
	<quote>contaminará</quote> el espacio de nombres global, que
	implicaría volver al mundo pre-espacios de nombres de C++.
      </para>
    </sect2>
  </sect1>


<!-- revisando por aquí: David Villa -->


  <sect1>
    <title>Miembros estáticos en C++</title>

    <!--There are times when
    you need a single storage space to be used by all objects of a
    class. In C, you would use a global variable, but this is not very
    safe. Global data can be modified by anyone, and its name can clash
    with other identical names in a large project. It would be ideal if
    the data could be stored as if it were global, but be hidden inside
    a class, and clearly associated with that class.
    -->

    <para>
      A veces se necesita un único espacio de almacenamiento para
      utilizado por todos los objetos de una clase. En C, podría usar
      una variable global pero eso no es muy seguro. Los datos
      globales pueden ser modificados por todo el mundo y su nombre
      puede chocar con otros idénticos si es un proyecto grande. Sería
      ideal si los datos pudiesen almacenarse como si fuesen
      globales pero ocultos dentro de una clase y claramente asociados
      con esa clase.
    </para>

    <!--
    This is accomplished with static data members inside a class. There
    is a single piece of storage for a static data member, regardless of
    how many objects of that class you create. All objects share the
    same static storage space for that data member, so it is a way for
    them to "communicate" with each other. But the static data
    belongs to the class; its name is scoped inside the class and it can
    be public, private, or protected.  -->

    <para>
      Esto es posible usando atributos <kw>static</kw>. Existe una
      única porción de espacio para los atributos <kw>static</kw>,
      independientemente del número de objetos de dicha clase que se
      hayan creado. Todos los objetos comparten el mismo espacio de
      almacenamiento <kw>static</kw> para ese atributo, constituyendo
      una forma de <quote>comunicarse</quote> entre ellos. Pero los
      datos <kw>static</kw> pertenecen a la clase; su nombre está
      restringido al interior de la clase y puede ser <kw>public</kw>,
      <kw>private</kw> o <kw>protected</kw>.
    </para>

    <sect2>
      <title>Definición del almacenamiento para atributos estáticos</title>

      <!-- Because static data has a single piece of storage
      regardless of how many objects are created, that storage must be
      defined in a single place. The compiler will not allocate storage
      for you. The linker will report an error if a static data member
      is declared but not defined.
      -->

      <para>
	Puesto que los datos <kw>static</kw> tienen una única porción
	de memoria donde almacenarse, independientemente del número de
	objetos creados, esa porción debe ser definida en un único
	sitio.  El compilador no reservará espacio de almacenamiento
	por usted. El enlazador reportará un error si un atributo
	miembro es declarado pero no definido.
      </para>

      <!--
      The definition must occur outside the class (no inlining is
      allowed), and only one definition is allowed. Thus, it is common
      to put it in the implementation file for the class. The syntax
      sometimes gives people trouble, but it is actually quite
      logical. For example, if you create a static data member inside a
      class like this:
      -->
      <para>
	La definición debe realizarse fuera de la clase (no se permite
	el uso de la sentencia <kw>inline</kw>), y sólo está permitida
	una definición. Es por ello que habitualmente se incluye en el
	fichero de implementación de la clase. La sintaxis suele traer
	problemas, pero en realidad es bastante lógica. Por ejemplo,
	si crea un atributo estático dentro de una clase de la
	siguiente forma:
      </para>

<programlisting>
class A {
  static int i;
public:
  //...
};
</programlisting>

      <!-- Then you must define storage for that static data member in
      the definition file like this: -->

      <para>
	Deberá definir el almacenamiento para ese atributo estático en
	el fichero de definición de la siguiente manera:
      </para>


      <programlisting>
	int A::i = 1;
      </programlisting>

      <!--
      If you were to define an ordinary global variable, you would say
      -->

      <para>
	Si quisiera definir una variable global ordinaria, debería
	utilizar
      </para>

      <programlisting>
	int i = 1;
      </programlisting>

      <!-- but here, the scope resolution operator and the class name
      are used to specify A::i.  -->

      <para>
	pero aquí, el operador de resolución de ámbito y el nombre de
	la clase se utilizan para especificar <code>A::i</code>.
      </para>

      <!-- Some people have trouble with the idea that A::i is private,
      and yet here's something that seems to be manipulating it right
      out in the open. Doesn't this break the protection mechanism? It's
      a completely safe practice for two reasons. First, the only place
      this initialization is legal is in the definition. Indeed, if the
      static data were an object with a constructor, you would call the
      constructor instead of using the = operator. Second, once the
      definition has been made, the end-user cannot make a second
      definition - the linker will report an error. And the class
      creator is forced to create the definition or the code won't link
      during testing. This ensures that the definition happens only once
      and that it's in the hands of the class creator.

      The entire initialization expression for a static member is in the
      scope of the class. For example,
      -->

      <para>
	Algunas personas tienen problemas con la idea que
	<code>A::i</code> es <kw>private</kw>, y pese a ello parece
	haber algo que lo está manipulando abiertamente. ¿No rompe
	esto el mecanismo de protección? Ésta es una práctica
	completamente segura por dos razones. Primera, el único sitio
	donde esta inicialización es legal es en la
	definición. Efectivamente, si el dato <kw>static</kw> fuese un
	objeto con un constructor, habría llamado al constructor en
	lugar de utilizar el operador <oper>=</oper>. Segundo,
	una vez se ha realizado la definición, el usuario final no
	puede hacer una segunda definición puesto que el enlazador
	indicaría un error. Y el creador de la clase está forzado a
	crear la definición o el código no enlazaría en las
	pruebas. Esto asegura que la definición sólo sucede una vez y
	que es el creador de la clase quien la lleva a cabo.
      </para>

      <para>
	La expresión completa de inicialización para un atributo
	estático se realiza en el ámbito de la clase.  Por ejemplo,
      </para>


//: V1C10:Statinit.cpp



      <!-- Here, the qualification WithStatic:: extends the scope of
      WithStatic to the entire definition.  -->

      <para>
	Aquí el calificador <code>WithStatic::</code> extiende el
	ámbito de <classname>WithStatic</classname> a la definición
	completa.
      </para>

      <sect3>
	<title>Inicialización de vectores estáticos</title>

	<!-- Chapter 8 introduced the static const variable that allows
	you to define a constant value inside a class body. It's also
	possible to create arrays of static objects, both const and
	non-const. The syntax is reasonably consistent: -->

	<para>
	  El <link linkend="C08">capítulo 8</link> introdujo una
	  variable <code>static const</code> que le permite definir un
	  valor constante dentro del cuerpo de una clase. También es
	  posible crear arrays de objetos estáticos, ya sean
	  constantes o no constantes. La sintaxis es razonablemente
	  consistente:
	</para>


//: V1C10:StaticArray.cpp



	<!-- With static consts of integral types you can provide the
	definitions inside the class, but for everything else (including
	arrays of integral types, even if they are static const) you
	must provide a single external definition for the member. These
	definitions have internal linkage, so they can be placed in
	header files. The syntax for initializing static arrays is the
	same as for any aggregate, including automatic counting.

	You can also create static const objects of class types and
	arrays of such objects. However, you cannot initialize them
	using the "inline syntax" allowed for static consts of
	integral built-in types: -->

	<para>
	  Usando <code>static const</code> de tipos enteros puede
	  realizar las definiciones dentro de la clase, pero para
	  cualquier otro tipo (incluyendo listas de enteros, incluso
	  si estos son <code>static const</code>) debe realizar una
	  única definición externa para el atributo. Estas
	  definiciones tienen enlazado interno, por lo que pueden
	  incluirse en ficheros de cabecera. La sintaxis para
	  inicializar listas estáticas es la misma que para cualquier
	  agregado, incluyendo el conteo automático<literal
	  role="FIXME">automatic counting</literal>.
	</para>

	<para>
	  También puede crear objetos <code>static const</code> de
	  tipos de clase y listas de dichos objetos. De todas formas,
	  no puede inicializarlos utilizando la sintaxis tipo
	  <quote>inline</quote> permitida para <code>static
	  const</code> de tipos enteros básicos:
	</para>



//: V1C10:StaticObjectArrays.cpp



	<!-- The initialization of both const and non-const static
	arrays of class objects must be performed the same way,
	following the typical static definition syntax.  -->

	<para>
	  La inicialización de listas estáticas de objetos tanto
	  constantes como no constantes debe realizarse de la misma
	  manera, siguiendo la típica sintaxis de definición estática.
	</para>

      </sect3>
    </sect2>

    <sect2>
      <title>Clases anidadas y locales</title>

      <!-- You can easily put static data members in classes that are
      nested inside other classes. The definition of such members is an
      intuitive and obvious extension - you simply use another level
      of scope resolution. However, you cannot have static data members
      inside local classes (a local class is a class defined inside a
      function). Thus, -->

      <para>
	Puede colocar fácilmente atributos estáticos en clases que
	están anidadas dentro de otras clases. La definición de tales
	miembros es intuitiva y obvia (tan sólo utiliza otro nivel de
	resolución de ámbito). No obstante, no puede tener atributos
	estáticos dentro de clases locales (una clase local es una
	clase definida dentro de una función). Por tanto,
      </para>


//: V1C10:Local.cpp



      <!-- You can see the immediate problem with a static member in a
      local class: How do you describe the data member at file scope in
      order to define it? In practice, local classes are used very
      rarely.  -->

      <para>
	Ya puede ver el problema con atributos estáticos en clases
	locales: ¿Cómo describirá el dato miembro en el ámbito del
	fichero para poder definirlo? En la práctica, el uso de clases
	locales es muy poco común.
      </para>
    </sect2>

    <sect2>
      <title>Métodos estáticos</title>

      <!--
      You can also create static member functions that, like static
      data members, work for the class as a whole rather than for a
      particular object of a class. Instead of making a global function
      that lives in and "pollutes" the global or local namespace,
      you bring the function inside the class.  When you create a static
      member function, you are expressing an association with a
      particular class.

      You can call a static member function in the ordinary way, with
      the dot or the arrow, in association with an object. However, it's
      more typical to call a static member function by itself, without
      any specific object, using the scope-resolution operator, like
      this: -->


      <para>
	También puede crear métodos estáticos que, como los atributos
	estáticos, trabajan para la clase como un todo en lugar de
	para un objeto particular de la clase. En lugar de hacer una
	función global que viva en y <quote>contamine</quote> el
	espacio de nombres global o local, puede incluir el método
	dentro de la clase. Cuando crea un método estático, está
	expresando una asociación con una clase particular.
      </para>

      <para>
	Puede llamar a un miembro estáticos de la forma habitual, con
	el punto o la flecha, en asociación con un objeto. De todas
	formas, es más típico llamar a los métodos estáticos en si
	mismos, sin especificar ningún objeto, utilizando el operador
	de resolución de ámbito, como en el siguiente ejemplo:
      </para>



//: V1C10:SimpleStaticMemberFunction.cpp


      <!-- When you see static member functions in a class, remember
      that the designer intended that function to be conceptually
      associated with the class as a whole.
      -->
      <para>
	Cuando vea métodos estáticos en una clase, recuerde que el
	diseñador pretendía que esa función estuviese conceptualmente
	asociada a la clase como un todo.
      </para>

      <!--
      A static member function cannot access ordinary data members, only
      static data members. It can call only other static member
      functions. Normally, the address of the current object (this) is
      quietly passed in when any member function is called, but a static
      member has no this, which is the reason it cannot access ordinary
      members. Thus, you get the tiny increase in speed afforded by a
      global function because a static member function doesn't have the
      extra overhead of passing this.  At the same time you get the
      benefits of having the function inside the class.
      -->
      <para>
	Un método estático no puede acceder a los atributos
	ordinarios, sólo a los estáticos. Sólo puede llamar a otros
	métodos estáticos. Normalmente, la dirección del objeto actual
	(<kw>this</kw>) se pasa de forma encubierta cuando se llama a
	cualquier método, pero un miembro <kw>static</kw> no tiene
	<kw>this</kw>, que es la razón por la cual no puede acceder a
	los miembros ordinarios.  Por tanto, se obtiene el ligero
	incremento de velocidad proporcionado por una función global
	debido a que un método estático no implica la carga extra de
	tener que pasar <kw>this</kw>. Al mismo tiempo, obtiene los
	beneficios de tener la función dentro de la clase.
      </para>

      <!--
      For data members, static indicates that only one piece of storage
      for member data exists for all objects of a class. This parallels
      the use of static to define objects inside a function to mean that
      only one copy of a local variable is used for all calls of that
      function.
      -->
      <para>
	Para atributos, <kw>static</kw> indica que sólo existe un
	espacio de memoria por atributo para todos los objetos de la
	clase. Esto establece que el uso de <kw>static</kw> para
	definir objetos dentro de una función significa que sólo se
	utiliza una copia de una variable local para todas las
	llamadas a esa función.
      </para>


      <!--
      Here's an example showing static data members and static member
      functions used together: -->
      <para>
	Aquí aparece un ejemplo mostrando atributos y métodos
	estáticos utilizados conjuntamente:
      </para>


//: V1C10:StaticMemberFunctions.cpp


      <!-- Because they have no this pointer, static member functions
      can neither access non-static data members nor call non-static
      member functions.
      -->
      <para>
	Puesto que no tienen el puntero <kw>this</kw>, los métodos
	estáticos no pueden acceder a atributos no estáticos ni llamar
	a métodos no estáticos.
      </para>

      <!--
      Notice in main( ) that a static member can be selected using the
      usual dot or arrow syntax, associating that function with an
      object, but also with no object (because a static member is
      associated with a class, not a particular object), using the class
      name and scope resolution operator.
      -->
      <para>
	Note el lector que en <function>main()</function> un miembro
	estático puede seleccionarse utilizando la habitual sintaxis
	de punto o flecha, asociando la función con el objeto, pero
	también sin objeto (ya que un miembro estático está asociado
	con una clase, no con un objeto particular), utilizando el
	nombre de la clase y el operador de resolución de ámbito.
      </para>

      <!--
      Here's an interesting feature: Because of the way initialization
      happens for static member objects, you can put a static data
      member of the same class inside that class. Here's an example that
      allows only a single object of type Egg to exist by making the
      constructor private. You can access that object, but you can't
      create any new Egg objects: -->

      <para>
	He aquí una interesante característica: Debido a la forma en
	la que se inicializan los objetos miembro estáticos, es
	posible poner un atributos estático de la misma clase dento de
	dicha clase. He aquí un ejemplo que tan solo permite la
	existencia de un único objeto de tipo
	<classname>Egg</classname> definiendo el constructor
	privado. Puede acceder a este objeto pero no puede crear
	ningún otro objeto tipo <classname>Egg</classname>:
      </para>


//: V1C10:Singleton.cpp



      <!-- The initialization for E happens after the class declaration
      is complete, so the compiler has all the information it needs to
      allocate storage and make the constructor call.
      -->
      <para>
	La inicialización de <varname>e</varname> ocurre una vez se
	completa la declaración de la clase, por lo que el compilador
	tiene toda la información que necesita para reservar espacio y
	llamar al constructor.
      </para>

      <!--
      To completely prevent the creation of any other objects, something
      else has been added: a second private constructor called the
      copy-constructor. At this point in the book, you cannot know why
      this is necessary since the copy constructor will not be
      introduced until the next chapter.  However, as a sneak preview,
      if you were to remove the copy-constructor defined in the example
      above, you'd be able to create an Egg object like this: -->

      <para>
	Para impedir completamente la creación de cualquier otro
	objeto, se ha añadido algo más: un segundo constructor privado
	llamado <emphasis>constructor de copia</emphasis>. Llegados a
	este punto del libro, usted no puede saber porqué esto es
	necesario puesto que el constructor de copia no se estudiará
	hasta el <link linkend="C11">siguiente capítulo</link>. De
	todas formas, como un breve adelanto, si se propusiese retirar
	el constructor de copia definido en el ejemplo anterior, sería
	posible crear objetos Egg de la siguiente forma:
      </para>

<programlisting>
Egg e = *Egg::instance();
Egg e2(*Egg::instance());
</programlisting>

      <!-- Both of these use the copy-constructor, so to seal off that
      possibility the copy-constructor is declared as private (no
      definition is necessary because it never gets called). A large
      portion of the next chapter is a discussion of the
      copy-constructor so it should become clear to you then.  -->

      <para>
	Ambos utilizan el constructor de copia, por lo que para evitar
	esta posibilidad, se declara el constructor de copia como
	privado (no se requiere definición porque nunca va a ser
	llamado). Buena parte del siguiente capítulo es una discusión
	sobre el constructor de copia por lo que esto quedará más
	claro entonces.
      </para>
    </sect2>
  </sect1>

  <sect1>
    <title>Dependencia en la inicialización de variables
      estáticas</title>

    <!-- Within a specific translation unit, the order of initialization
    of static objects is guaranteed to be the order in which the object
    definitions appear in that translation unit. The order of
    destruction is guaranteed to be the reverse of the order of
    initialization.
    -->
    <para>
      Dentro de una unidad de traducción específica, está garantizado
      que el orden de inicialización de los objetos estáticos será el
      mismo que el de aparición de sus definiciones en la unidad de
      traducción.
    </para>

    <!--
    However, there is no guarantee concerning the order of
    initialization of static objects across translation units, and the
    language provides no way to specify this order. This can cause
    significant problems. As an example of an instant disaster (which
    will halt primitive operating systems and kill the process on
    sophisticated ones), if one file contains -->
    <para>
      No obstante, no hay garantías sobre el orden en que se
      inicializan los objetos estáticos entre diferentes unidades de
      traducción, y el lenguaje no proporciona ninguna forma de
      averiguarlo. Esto puede producir problemas significativos. Como
      ejemplo de desastre posible (que provocará el cuelgue de
      sistemas operativos primitivos o la necesidad de matar el
      proceso en otros más sofisticados), si un archivo contiene:
    </para>


//: V1C10:Out.cpp


    <!--
    and another file uses the out object in one of its initializers
    -->

    <para>
      y otro archivo utiliza el objeto <varname>out</varname> en uno
      de sus inicializadores
    </para>


//: V1C10:Oof.cpp



    <!-- the program may work, and it may not. If the programming
    environment builds the program so that the first file is initialized
    before the second file, then there will be no problem. However, if
    the second file is initialized before the first, the constructor for
    Oof relies upon the existence of out, which hasn't been constructed
    yet and this causes chaos.
    -->
    <para>
      el programa puede funcionar, o puede que no. Si el entorno de
      programación construye el programa de forma que el primer
      archivo sea inicializado después del segundo, no habrá
      problemas. Pero si el segundo archivo se inicializa antes que el
      primero, el constructor para <classname>Oof</classname> se
      sustenta en la existencia de <varname>out</varname>, que todavía
      no ha sido construido, lo que causa el caos.
    </para>

    <!--
    This problem only occurs with static object initializers that depend
    on each other. The statics in a translation unit are initialized
    before the first invocation of a function in that unit - but it
    could be after main( ). You can't be sure about the order of
    initialization of static objects if they're in different files.
    -->
    <para>
      Este problema sólo ocurre con inicializadores de objetos
      estáticos que dependen el uno del otro. Los estáticos dentro de
      cada unidad de traducción son inicializados antes de la primera
      invocación a cualquier función de esa unidad, aunque puede que
      después de <function>main()</function>. No puede estar seguro
      del orden de inicialización de objetos estáticos si están en
      archivos diferentes.
    </para>


    <!--
    FIXME: referencia bibliográfica
    A subtler example can be found in the ARM.[47] In one file you have
    at the global scope:
    -->
    <para>
      Un ejemplo sutil puede encontrarse en ARM.<footnote><para>Bjarne
	  Stroustrup and Margaret Ellis, The Annotated C++ Reference Manual,
	  Addison-Wesley, 1990, pp. 20-21.</para></footnote> en un archivo que
      aparece en el rango global:
    </para>

<programlisting>
extern int y;
int x = y + 1;
</programlisting>

    <!--
    and in a second file you have at the global scope:
    -->
    <para>
      y en un segundo archivo también en el ámbitoglobal:
    </para>

<programlisting>
extern int x;
int y = x + 1;
</programlisting>


    <!-- For all static objects, the linking-loading mechanism
    guarantees a static initialization to zero before the dynamic
    initialization specified by the programmer takes place. In the
    previous example, zeroing of the storage occupied by the fstream out
    object has no special meaning, so it is truly undefined until the
    constructor is called. However, with built-in types, initialization
    to zero does have meaning, and if the files are initialized in the
    order they are shown above, y begins as statically initialized to
    zero, so x becomes one, and y is dynamically initialized to
    two. However, if the files are initialized in the opposite order, x
    is statically initialized to zero, y is dynamically initialized to
    one, and x then becomes two.
    -->
    <para>
      Para todos los objetos estáticos, el mecanismo de carga-enlazado
      garantiza una inicialización estática a cero antes de la
      inicialización dinámica especificada por el programador. En el
      ejemplo anterior, la inicialización a cero de la zona de memoria
      ocupada por el objeto <code>fstream out</code> no tiene especial
      relevancia, por lo que realmente no está definido hasta que se
      llama al constructor. Pese a ello, en el caso de los tipos
      predefinidos, la inicialización a cero sí tiene importancia, y
      si los archivos son inicializados en el orden mostrado arriba, y
      empieza estáticamente inicializada a cero, por lo que
      <varname>x</varname> se convierte en uno, e <varname>y</varname>
      es dinámicamente inicializada a dos. Pero si los archivos fuesen
      inicializados en orden opuesto, <varname>x</varname> sería
      estáticamente inicializada a cero, <varname>y</varname>
      dinámicamente inicializada a uno y después, <varname>x</varname>
      pasaría a valer dos.
    </para>

    <!--
    Programmers must be aware of this because they can create a program
    with static initialization dependencies and get it working on one
    platform, but move it to another compiling environment where it
    suddenly, mysteriously, doesn't work.
    -->

    <para>
      Los programadores deben estar al tanto de esto porque puede darse
      el caso de crear un programa con dependencias de inicialización
      estáticas que funcionen en una plataforma determinada y, de golpe
      y misteriosamente, compilarlo en otro entorno y que deje de
      funcionar.
    </para>

    <sect2>
      <title>Qué hacer</title>
      <!--
      There are three approaches to dealing with this problem:

      1. Don't do it. Avoiding static initialization dependencies is the best solution.
      2. If you must do it, put the critical static object definitions
      in a single file, so you can
      portably control their initialization by putting them in the correct order.
      3. If you're convinced it's unavoidable to scatter static
      objects across translation units - as in the case of a library,
      where you can't control the programmer  who uses it - there are
      two programmatic techniques to solve the problem.
      -->

      <para>
	Existen tres aproximaciones para tratar con este problema:
      </para>

      <orderedlist>
	<listitem>
	  <para>
	    No hacerlo. Evitar las dependencias de inicialización
	    estática es la mejor solución.
	  </para>
	</listitem>
	<listitem>
	  <para>
	    Si debe hacerlo, coloque las definiciones de objetos
	    estáticos críticos en un único fichero, de forma que pueda
	    controlar, de forma portable, su inicialización
	    colocándolos en el orden correcto.
	  </para>
	</listitem>
	<listitem>
	  <para>
	    Si está convencido que es inevitable dispersar objetos
	    estáticos entre unidades de traducción diferentes (como
	    en el caso de una librería, donde no puede controlar el
	    programa que la usa), hay dos técnicas de programación
	    para solventar el problema.
	  </para>
	</listitem>
      </orderedlist>


      <sect3>
	<title>Técnica uno</title>

      <!--
      Technique one This technique was pioneered by Jerry Schwarz
      while creating the iostream library (because the definitions
      for cin, cout, and cerr are static and live in a separate
      file). It's actually inferior to the second technique but it's
      been around a long time and so you may come across code that
      uses it; thus it's important that you understand how it works.
      -->
      <para>
	  El pionero de esta técnica fue <author>
	    <firstname>Jerry</firstname>
	    <surname>Schwarz</surname></author> mientras creaba la
	    librería <filename>iostream</filename> (puesto que las
	    definiciones para <varname>cin</varname>,
	    <varname>cout</varname> y <varname>cerr</varname> son
	    <kw>static</kw> y residen en archivos
	    diferentes). Realmente es inferior a la segunda técnica
	    pero ha pululado durante mucho tiempo por lo que puede
	    encontrarse con código que la utilice; así pues, es
	    importante que entienda como funciona.
      </para>

      <!--
      This technique requires an additional class in your library header
      file. This class is responsible for the dynamic initialization
      of your library's static objects. Here is a simple example:
      -->
      <para>
	Esta técnica requiere una clase adicional en su archivo de
	cabecera. Esta clase es la responsable de la inicialización
	dinámica de sus objetos estáticos de librería. He aquí un
	ejemplo simple:
      </para>


//: V1C10:Initializer.h


      <!-- The declarations for x and y announce only that these objects
      exist, but they don't allocate storage for the objects. However,
      the definition for the Initializer init allocates storage for that
      object in every file where the header is included. But because the
      name is <kw>static</kw> (controlling visibility this time, not the way
      storage is allocated; storage is at file scope by default), it is
      visible only within that translation unit, so the linker will not
      complain about multiple definition errors.

      Here is the file containing the definitions for x, y, and initCount:
      -->

      <para>
	  Las declaraciones para <varname>x</varname> e
	<varname>y</varname> anuncian tan sólo que esos objetos
	existen, pero no reservan espacio para los objetos. No
	obstante, la definición para el <code>Initializer init</code>
	reserva espacio para ese objeto en cada archivo en que se
	incluya el archivo de cabecera. Pero como el nombre es
	<kw>static</kw> (en esta ocasión controlando la visibilidad,
	no la forma en la que se almacena; el almacenamiento se
	produce a nivel de archivo por defecto), sólo es visible en
	esa unidad de traducción, por lo que el enlazador no se
	quejará por múltiples errores de definición.
      </para>

      <para>
	  He aquí el archivo con las definiciones para
	  <varname>x</varname>, <varname>y</varname> e
	  <varname>initCount</varname>:
      </para>


//: V1C10:InitializerDefs.cpp


      <!-- (Of course, a file static instance of init is also placed in
      this file when the header is included.)  Suppose that two other
      files are created by the library user: -->

	<para>
	  (Por supuesto, una instancia <emphasis>estática de
	    fichero</emphasis> de <varname>init</varname> también se
	    incluye en este archivo cuando se incluye el archivo de
	    cabecera. Suponga que otros dos archivos se crean por
	    la librería del usuario:
      </para>


//: V1C10:Initializer.cpp


      <para>
	y
      </para>


//: V1C10:Initializer2.cpp



      <!-- Now it doesn't matter which translation unit is initialized
      first. The first time a translation unit containing Initializer.h
      is initialized, initCount will be zero so the initialization will
      be performed. (This depends heavily on the fact that the static
      storage área is set to zero before any dynamic initialization
      takes place.) For all the rest of the translation units, initCount
      will be nonzero and the initialization will be skipped. Cleanup
      happens in the reverse order, and ~Initializer( ) ensures that it
      will happen only once.
	-->
      <para>
	Ahora no importa en qué unidad de traducción se inicializa
	primero. La primera vez que una unidad de traducción que
	contenga <filename>Initializer.h</filename> se inicialice,
	<varname>initCount</varname> será cero por lo que la
	inicialización será llevada a cabo. (Esto depende en gran
	medida en el hecho que la zona de almacenamiento estático está
	a cero antes de que cualquier inicialización dinámica se lleve
	a cabo). Para el resto de unidades de traducción,
	<varname>initCount</varname> no será cero y se eludirá la
	inicialización. La limpieza ocurre en el orden inverso, y
	<function>~Initializer()</function> asegura que sólo ocurrirá
	una vez.
      </para>

	<!--
      This example used built-in types as the global static objects. The
      technique also works with classes, but those objects must then be
      dynamically initialized by the Initializer class. One way to do
      this is to create the classes without constructors and
      destructors, but instead with initialization and cleanup member
      functions using different names. A more common approach, however,
      is to have pointers to objects and to create them using new inside
      Initializer( ).  -->
      <para>
	Este ejemplo utiliza tipos del lenguaje como objetos estáticos
	globales. Esta técnica también funciona con clases, pero esos
	objetos deben ser inicializados dinámicamente por la clase
	<classname>Initializer</classname>.  Una forma de hacer esto
	es creando clases sin constructores ni destructores, pero sí
	con métodos de inicialización y limpieza con nombres
	diferentes. Una aproximación más común, de todas formas, es
	tener punteros a objetos y crearlos utilizando <kw>new</kw>
	  dentro de <function>Initializer()</function>.
      </para>
      </sect3>

      <sect3>
	<!-- Technique two -->
	<title>Técnica dos</title>

      <!--
      Long after technique one was in use, someone (I don't know who)
      came up with the technique explained in this section, which is
      much simpler and cleaner than technique one. The fact that it took
      so long to discover is a tribute to the complexity of C++.
      -->
      <para>
	Bastante después de la aparición de la técnica uno, alguien
	(no sé quien) llegó con la técnica explicada en esta sección,
	que es mucho más simple y limpia que la anterior. El hecho de
	que tardase tanto en descubrirse es un tributo a la
	complejidad de C++.
      </para>


	<!--
	This technique relies on the fact that static objects inside
      functions are initialized the first time (only) that the function
      is called. Keep in mind that the problem we're really trying to
      solve here is not when the static objects are initialized (that
      can be controlled separately) but rather making sure that the
      initialization happens in the proper order.
	-->
      <para>
	Esta técnica se sustenta en el hecho de que los objetos
	estáticos dentro de funciones (sólo) se inicializan la primera
	vez que se llama a la función. Tenga presente que el problema
	que estamos intentando resolver aquí no es cuando se
	inicializan los objetos estáticos (que se puede controlar
	separadamente) sino más bien asegurarnos de que la
	inicialización ocurre en el orden adecuado.
      </para>

	<!--
	 This technique is very neat and clever. For any initialization
      dependency, you place a static object inside a function that
      returns a reference to that object. This way, the only way you can
      access the static object is by calling the function, and if that
      object needs to access other static objects on which it is
      dependent it must call their functions. And the first time a
      function is called, it forces the initialization to take
      place. The order of static initialization is guaranteed to be
      correct because of the design of the code, not because of an
      arbitrary order established by the linker.
	-->
      <para>
	Esta técnica es muy limpia y astuta. Para cualquier
	dependencia de inicialización, se coloca un objeto estático
	dentro de una función que devuelve una referencia a ese
	objeto. De esta forma, la única manera de acceder al objeto
	estático es llamando a la función, y si ese objeto necesita
	acceder a otros objetos estáticos de los que depende, debe
	llamar a sus funciones. Y la primera vez que se llama a una
	función, se fuerza a llevar a cabo la inicialización. Está
	garantizado que el orden de la inicialización será correcto
	debido al diseño del código, no al orden que arbitrariamente
	decide el enlazador.
      </para>

	<!--
	To set up an example, here are two classes that depend on each
      other. The first one contains a bool that is initialized only by
      the constructor, so you can tell if the constructor has been
      called for a static instance of the class (the static storage área
      is initialized to zero at program startup, which produces a false
      value for the bool if the constructor has not been called):
	-->
      <para>
	  Para mostrar un ejemplo, aquí tenemos dos clases que
	  dependen la una de la otra. La primera contiene un
	  <type>bool</type> que sólo se inicializa por el constructor,
	  por lo que se puede decir si se ha llamado el constructor
	  por una instancia estática de la clase (el área de
	  almacenamiento estático se inicializa a cero al inicio del
	  programa, lo que produce un valor <kw>false</kw> para el
	  <type>bool</type> si el constructor no ha sido llamado).
      </para>



//: V1C10:Dependency1.h


      <!-- The constructor also announces when it is being called, and
      you can print( ) the state of the object to find out if it has
      been initialized.

      The second class is initialized from an object of the first
      class, which is what will cause the dependency: -->

      <para>
	El constructor también indica cuando ha sido llamado, y es
	posible el estado del objeto para averiguar si ha sido
	inicializado.
      </para>

      <para>
	La segunda clase es inicializada por un objeto de la primera
	clase, que es lo que causa la dependencia:
      </para>


//: V1C10:Dependency2.h


      <!-- The constructor announces itself and prints the state of the
      d1 object so you can see if it has been initialized by the time
      the constructor is called.

      To demonstrate what can go wrong, the following file first puts
      the static object definitions in the wrong order, as they would
      occur if the linker happened to initialize the Dependency2 object
      before the Dependency1 object. Then the order is reversed to show
      how it works correctly if the order happens to be "right."
      Lastly, technique two is demonstrated.  -->

      <para>
	El constructor se anuncia a si mismo y imprime el estado del
	  objeto <varname>d1</varname> por lo que puede ver si éste se
	  ha inicializado cuando se llama al constructor.
      </para>

      <para>
	Para demostrar lo que puede ir mal, el siguiente archivo
	primero pone las definiciones de los objetos estáticos en el
	orden incorrecto, tal y como sucedería si el enlazador
	inicializase el objeto <classname>Dependency2</classname>
	antes del <classname>Dependency1</classname>. Después se
	invierte el orden para mostrar que funciona correctamente si
	el orden resulta ser el correcto. Finalmente, se muestra la
	técnica dos.
      </para>

      <!-- To provide more readable output, the function separator( ) is
      created. The trick is that you can't call a function globally
      unless that function is being used to perform the initialization
      of a variable, so separator( ) returns a dummy value that is used
      to initialize a couple of global variables.  -->
      <para>
	  Para proporcionar una salida más legible, se ha creado la
	  función <function>separator()</function>. El truco está en
	  que usted no puede llamar a la función globalmente a menos
	  que la función sea utilizada para llevar a cabo la
	  inicialización de la variable, por lo que
	  <function>separator()</function> devuelve un valor absurdo
	  que es utilizado para inicializar un par de variables
	  globales.
      </para>


//: V1C10:Technique2.cpp


      <!-- The functions d1( ) and d2( ) wrap static instances of
      Dependency1 and Dependency2 objects. Now, the only way you can get
      to the static objects is by calling the functions and that forces
      static initialization on the first function call. This means that
      initialization is guaranteed to be correct, which you'll see when
      you run the program and look at the output.
	-->
      <para>
	  Las funciones <function>d1()</function> y
	<function>d2()</function> contienen instancias estáticas de
	los objetos <classname>Dependency1</classname> y
	<classname>Dependency2</classname>.  Ahora, la única forma de
	acceder a los objetos estáticos es llamando a las funciones y
	eso fuerza la inicialización estática en la primera llamada a
	la función. Esto significa que se garantiza la inicialización
	correcta, cosa que verá cuando lance el programa y observe la
	salida.
      </para>

	<!--
      Here's how you would actually organize the code to use the
      technique. Ordinarily, the static objects would be defined in
      separate files (because you're forced to for some reason; remember
      that defining the static objects in separate files is what causes
      the problem), so instead you define the wrapping functions in
      separate files. But they'll need to be declared in header files:
      -->
      <para>
	He aquí como debe organizar el código para usar esta
	técnica. Ordinariamente, los objetos estáticos deben ser
	definidos en archivos diferentes (puesto que se ha visto
	forzado a ello por alguna razón; recuerde que definir objetos
	estáticos en archivos diferentes es lo que causa el problema),
	por lo que definirá las funciones envoltorio <literal
	role="FIXME">wrapping functions</literal>) en archivos
	diferentes. Pero éstas necesitan estar declaradas en los
	archivos de cabecera:
      </para>


//: V1C10:Dependency1StatFun.h


      <!-- Actually, the "extern" is redundant for the function
      declaration. Here's the second header file: -->

      <para>
	  En realidad, el <quote>extern</quote> es redundante para la
	declaración de la función. Éste es el segundo archivo de
	cabecera:
      </para>


//: V1C10:Dependency2StatFun.h


      <!-- Now, in the implementation files where you would previously
      have placed the static object definitions, you instead place the
      wrapping function definitions: -->

      <para>
	Ahora, en los archivos de implementación donde previamente
	habría situado las definiciones de los objetos estáticos, situará
	las definiciones de las funciones envoltorio:
      </para>


//: V1C10:Dependency1StatFun.cpp


      <!--
      Presumably, other code might also be placed in these files. Here's the other file:
      -->

      <para>
	Presumiblemente, otro código puede también componer esos
	archivos. He aquí otro archivo:
      </para>



//: V1C10:Dependency2StatFun.cpp


      <!-- So now there are two files that could be linked in any order
      and if they contained ordinary static objects could produce any
      order of initialization. But since they contain the wrapping
      functions, there's no threat of incorrect initialization: -->
      <para>
	Ahora hay dos archivos que pueden ser enlazados en cualquier
	orden y si contuviesen objetos estáticos ordinarios podría
	producirse cualquier orden de inicialización. Pero como
	contienen funciones envoltorio, no hay posibilidad de
	inicialización incorrecta:
      </para>


//: V1C10:Technique2b.cpp


      <!-- When you run this program you'll see that the initialization
      of the Dependency1 static object always happens before the
      initialization of the Dependency2 static object. You can also see
      that this is a much simpler approach than technique one.
	-->
      <para>
	Cuando ejecute este programa verá que la inicialización del
	  objeto estático <classname>Dependency1</classname> siempre
	  se lleva a cabo antes de la inicialización del objeto
	  estático <classname>Dependency2</classname>. También puede
	  ver que ésta es una solución bastante más simple que la de
	  la uno.
      </para>

	<!--
      You might be tempted to write d1( ) and d2( ) as inline functions
      inside their respective header files, but this is something you
      must definitely not do. An inline function can be duplicated in
      every file in which it appears - and this duplication includes
      the static object definition.  Because inline functions
      automatically default to internal linkage, this would result in
      having multiple static objects across the various translation
      units, which would certainly cause problems.  So you must ensure
      that there is only one definition of each wrapping function, and
      this means not making the wrapping functions inline.  -->
      <para>
	  Puede verse tentado a escribir <function>d1()</function> y
	  <function>d2()</function> como funciones <kw>inline</kw>
	  dentro de sus respectivos archivos de cabecera, pero eso es
	  algo que, definitivamente, no debe hacer. Una función
	  <kw>inline</kw> puede ser duplicada en cada archivo en el
	  que aparezca y esa duplicación incluye la definición de los
	  objetos estáticos. Puesto que las funciones <kw>inline</kw>
	  llevan asociado por defecto enlazado interno, esto provocará
	  la aparición de múltiples objetos estáticos entre las
	  diversas unidades de traducción, lo que ciertamente causará
	  problemas. Es por eso que debe asegurarse que sólo existe
	  una única definición para cada función contenedora, y eso
	  significa no hacerlas <kw>inline</kw>.
      </para>
      </sect3>
    </sect2>
  </sect1>

  <sect1>
    <title>Especificaciones de enlazado alternativo</title>

    <!-- What happens if you're writing a program in C++ and you want to
    use a C library? If you make the C function declaration, -->

    <para>
      ¿Qué pasa si está escribiendo un programa en C++ y quiere usar
      una librería de C? Si hace uso de la declaración de funciones de
      C,
    </para>

    <programlisting>
	float f(int a, char b);
    </programlisting>

    <!-- the C++ compiler will decorate this name to something like
    _f_int_char to support function overloading (and type-safe
    linkage). However, the C compiler that compiled your C library has
    most definitely not decorated the name, so its internal name will be
    _f. Thus, the linker will not be able to resolve your C++ calls to
    f( ).
    -->
    <para>
      el compilador de C++ adornará el nombre como algo tipo
      <literal>_f_int_char</literal> para permitir la sobrecarga de la
      función (y el enlazado con verificación de tipos). De todas
      formas, el compilador de C que compiló su librería C
      definitivamente no decoró ese nombre, por lo que su nombre
      interno será <literal>_f</literal>. Así pues, el enlazador no
      será capaz de resolver sus llamadas tipo C++ a
      <function>f()</function>.
    </para>

    <!--
    The escape mechanism provided in C++ is the alternate linkage
    specification, which was produced in the language by overloading the
    extern keyword. The extern is followed by a string that specifies
    the linkage you want for the declaration, followed by the
    declaration: -->
    <para>
      La forma de resolver esto que se propone en C++ es la
      <emphasis>especificación de enlazado alternativo</emphasis>, que
      se produjo en el lenguaje sobrecargando la palabra clave
      <kw>extern</kw>. A la palabra clave <kw>extern</kw> le sigue una
      cadena que especifica el enlazado deseado para la declaración,
      seguido por la declaración:
    </para>

    <programlisting>
	extern "C" float f(int a, char b);
    </programlisting>

    <!-- This tells the compiler to give C linkage to f( ) so that the
	compiler doesn't decorate the name.  The only two types of
	linkage specifications supported by the standard are "C"
	and "C++," but compiler vendors have the option of
	supporting other languages in the same way.

    If you have a group of declarations with alternate linkage, put them
    inside braces, like this: -->

    <para>
      Esto le dice al compilador que <function>f()</function> tiene
      enlazado tipo C, de forma que el compilador no decora el
      nombre. Las dos únicas especificaciones de enlazado soportadas
      por el estándar son <quote role="en">C</quote> y <quote
      role="en">C++</quote>, pero algunos vendedores ofrecen
      compiladores que también soportan otros lenguajes.
    </para>

    <para>
      Si tiene un grupo de declaraciones con enlazado alternativo,
      póngalas entre llaves, como a continuación:
    </para>


<programlisting>
extern "C" {
    float f(int a, char b);
    double d(int a, char b);
}
</programlisting>

    <!--
    Or, for a header file,
    -->
    <para>
      O, para archivos de cabecera,
    </para>

    <programlisting>
extern "C" {
    #include "Myheader.h"
}
    </programlisting>

    <!-- Most C++ compiler vendors handle the alternate linkage
    specifications inside their header files that work with both C and
    C++, so you don't have to worry about it.  -->

    <para>
      La mayoría de compiladores disponibles de C++ manejan las
      especificaciones de enlazado alternativo dentro de sus propios
      archivos de cabecera que trabajan tanto con C como con C++, por
      lo que no tiene que preocuparse de eso.
    </para>
  </sect1>

  <sect1>
    <title>Resumen</title>

    <!-- The static keyword can be confusing because in some sitúations
    it controls the location of storage, and in others it controls
    visibility and linkage of a name.

    With the introduction of C++ namespaces, you have an improved and
    more flexible alternative to control the proliferation of names in
    large projects.

    The use of static inside classes is one more way to control names in
    a program. The names do not clash with global names, and the
    visibility and access is kept within the program, giving you greater
    control in the maintenance of your code.  -->

    <para>
      La palabra clave <kw>static</kw> puede llevar a confusión porque
      en algunas situaciones controla la reserva de espacio en
      memoria, y en otras controla la visibilidad y enlazado del
      nombre.
    </para>

    <para>
      Con la introducción de los espacios de nombres de C++, dispone
      de una alternativa mejorada y más flexible para controlar la
      proliferación de nombres en proyectos grandes.
    </para>

    <para>
      El uso de <kw>static</kw> dentro de clases es un método más para
      controlar los nombres de un programa. Los nombres no colisionan
      con nombres globales, y la visibilidad y acceso se mantiene
      dentro del programa, dándole un mayor control para el
      mantenimiento de su código.
    </para>
  </sect1>

  <sect1>
    <title>Ejercicios</title>

    <!-- Solutions to selected exercises can be found in the electronic
    document The Thinking in C++ Annotated Solution Guide, available for
    a small fee from www.BruceEckel.com.

     1. Create a function with a static variable that is a pointer (with
     a default argument of zero). When the caller provides a value for
     this argument it is used to point at the beginning of an array of
     int. If you call the function with a zero argument (using the
     default argument), the function returns the next value in the
     array, until it sees a "-1" value in the array (to act as an
     end-of-array indicator). Exercise this function in main( ).

     2. Create a function that returns the next value in a Fibonacci
     sequence every time you call it. Add an argument that is a bool
     with a default value of false such that when you give the argument
     with true it "resets" the function to the beginning of the
     Fibonacci sequence. Exercise this function in main( ).

     3. Create a class that holds an array of ints. Set the size of the
     array using static const int inside the class.  Add a const int
     variable, and initialize it in the constructor initializer list;
     make the constructor inline.  Add a static int member variable and
     initialize it to a specific value. Add a static member function
     that prints the static data member. Add an inline member function
     called print( ) to print out all the values in the array and to
     call the static member function. Exercise this class in main( ).
     -->

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

    <orderedlist>
      <listitem>
	<para>
	  Cree una función con una variable estática que sea un
	  puntero (con un argumento por defecto igual cero).  Cuando
	  la función que realice la llamada proporcione un valor para
	  ese argumento se usará para apuntar al principio de un
	  array de <type>int</type>. Si se llama a la función con el
	  argumento cero (utilizando el argumento por defecto), la
	  función devuelve el siguiente valor del array, hasta que
	  llegue a un valor <literal>-1</literal> en el array (que
	  actuará como señal de final). Experimente con esta función en
	  <function>main()</function>.
	</para>
      </listitem>
      <listitem>
	<para>
	  Cree una función que devuelva el siguiente valor de una
	  serie de Fibonacci cada vez que sea llamada. Añada un
	  argumento que de tipo <type>bool</type> con valor por
	  defecto <kw>false</kw> tal que cuando el argumento valga
	  <kw>true</kw> <quote>reinicie</quote> la función al
	  principio de la serie de Fibonacci. Experimente con esta función en
	  <function>main()</function>.
	</para>
      </listitem>
      <listitem>
	<para>
	  Cree una clase que contenga un array de
	  <type>int</type>. Especifique la dimensión del array
	  utilizando <code>static const int</code> dentro de la
	  clase. Añada una variable <code>const int</code> e
	  inicialícela en la lista de inicialización del
	  constructor. Haga al constructor <kw>inline</kw>. Añada un
	  atributo <type>static int</type> e inicialícelo a un valor
	  específico. Añada un método estático que imprima el atributo
	  estático. Añada un miembro <kw>inline</kw> llamado
	  <function>print()</function> que imprima todos los valores
	  del array y que llame al método estático. Experimente con esta
	  clase en <function>main()</function>.
	</para>
      </listitem>

    <!--
      4. Create a class called Monitor that keeps track of thenumber
    of times that its incident( ) member function has been called. Add a
    print( ) member function that displays the number of incidents. Now
    create a global function (not a member function) containing a static
    Monitor object. Each time you call the function it should call
    incident( ), then print( ) member function to display the incident
    count. Exercise the function in main( ).

    5. Modify the Monitor class from Exercise 4 so that you can
    decrement( ) the incident count. Make a class Monitor2 that takes as
    a constructor argument a pointer to a Monitor1, and which stores
    that pointer and calls incident( ) and print( ). In the destructor
    for Monitor2, call decrement( ) and print( ). Now make a static
    object of Monitor2 inside a function. Inside main( ), experiment
    with calling the function and not calling the function to see what
    happens with the destructor of Monitor2.
      -->

      <listitem>
	<para>
	  Cree una clase llamada <classname>Monitor</classname> que
	  mantenga el registro del número de veces que ha sido llamado
	  su método <function>incident()</function>. Añada un método
	  <function>print()</function> que muestre por pantalla el
	  número de incidentes. Ahora cree una función global (no un
	  método) que contenga un objeto estático
	  <classname>Monitor</classname>. Cada vez que llame a la
	  función debe llamar a <function>incident()</function>,
	  después al método <function>print()</function> para sacar
	  por pantalla el contador de incidentes. Experimente con la función
	  en <function>main()</function>.
	</para>
      </listitem>
      <listitem>
	<para>
	  Modifique la clase <classname>Monitor</classname> del
	  Ejercicio 4 de forma que pueda decrementar
	  (<function>decrement()</function>) el contador de
	  incidentes. Cree una clase llamada
	  <classname>Monitor2</classname> que tome como argumento del
	  constructor un puntero a <classname>Monitor1</classname>, y
	  que almacene ese puntero y llame a
	  <function>incident()</function> y
	  <function>print()</function>. En el destructor para
	  <classname>Monitor2</classname>, llame a
	  <function>decrement()</function> y
	  <function>print()</function>. Cree ahora un objeto estático
	  de <classname>Monitor2</classname> dentro de una
	  función. Dentro de <function>main()</function>, experimente
	  llamando y no llamando a la función para ver qué pasa con el
	  destructor de <classname>Monitor2</classname>.
	</para>
      </listitem>

      <!--
    6. Make a global object of Monitor2 and see what happens.

    7. Create a class with a destructor that prints a message and then
    calls exit( ). Create a global object of this class and see what
    happens.

    8. In StaticDestructors.cpp, experiment with the order of
    constructor and destructor calls by calling f( ) and g( ) inside
    main( ) in different orders. Does your compiler get it right?

    9. In StaticDestructors.cpp, test the default error handling of your
    implementation by turning the original definition of out into an
    extern declaration and putting the actual definition after the
    definition of a (whose Obj constructor sends information to
    out). Make sure there's nothing else important running on your
    machine when you run the program or that your machine will handle
    faults robustly.

    10. Prove that file static variables in header files don't clash
    with each other when included in more than one cpp file.  -->

      <listitem>
	<para>
	  Cree un objeto global de clase
	  <classname>Monitor2</classname> y vea qué sucede.
	</para>
      </listitem>
      <listitem>
	<para>
	  Cree una clase con un destructor que imprima un mensaje y
	  después llame a <function>exit()</function>. Cree un objeto
	  global de esa clase y vea qué pasa.
	</para>
      </listitem>
      <listitem>
	<para>
	  En <filename>StaticDestructors.cpp</filename>, experimente
	  con el orden de llamada de los constructores y destructores
	  llamando a <function>f()</function> y
	  <function>g()</function> dentro de
	  <function>main()</function> en diferentes órdenes. ¿Su
	  compilador inicializa los objetos de la forma correcta?
	</para>
      </listitem>
      <listitem>
	<para>
	  En <filename>StaticDestructors.cpp</filename>, pruebe el
	  manejo de errores por defecto de su implementación
	  convirtiendo la definición original de
	  <varname>out</varname> dentro de una declaración
	  <kw>extern</kw>, y poniendo la definición real después de la
	  definición de <varname>a</varname> (donde el constructor de
	  <classname>Obj</classname> manda información a
	  <varname>out</varname>). Asegúrese que no hay ningún otro
	  programa importante funcionando en su máquina cuando ejecute
	  el código o que su máquina maneje las faltas robustamente.
	</para>
      </listitem>
      <listitem>
	<para>
	  Pruebe que las variables estáticas de fichero en los
	  archivos de cabecera no chocan entre sí cuando son incluidas
	  en más de un archivo <filename>cpp</filename>.
	</para>
      </listitem>

    <!-- 11. Create a simple class containing an int, a constructor that
    initializes the int from its argument, a member function to set the
    int from its argument, and a print( ) function that prints the
    int. Put your class in a header file, and include the header file in
    two cpp files. In one cpp file make an instance of your class, and
    in the other declare that identifier extern and test it inside main(
    ). Remember, you'll have to link the two object files or else the
    linker won't find the object.

    12. Make the instance of the object in Exercise 11 static and verify
    that it cannot be found by the linker because of this.

    13. Declare a function in a header file. Define the function in one
    cpp file and call it inside main( ) in a second cpp file. Compile
    and verify that it works. Now change the function definition so that
    it is static and verify that the linker cannot find it.

    14. Modify Volatile.cpp from Chapter 8 to make comm::isr( )
    something that could actually work as an interrupt service
    routine. Hint: an interrupt service routine doesn't take any
    arguments.  -->


      <listitem>
	<para>
	  Cree una única clase que contenga un <type>int</type>, un
	  constructor que inicialice el <type>int</type> con su
	  argumento, un método que cambie el valor del
	  <type>int</type> con su argumento y una función
	  <function>print()</function> que muestre por pantalla el
	  <type>int</type>. Coloque su clase en un archivo de cabecera
	  e incluya dicho archivo en dos archivos
	  <filename>cpp</filename>. En uno de ellos cree una instancia
	  de la clase y en la otra declare ese identificador como
	  <kw>extern</kw> y pruebe dentro de
	  <function>main()</function>. Recuerde, debe enlazar los dos
	  archivos objeto o de lo contrario el enlazador no encontrará
	  el objeto.
	</para>
      </listitem>
      <listitem>
	<para>
	  Cree la instancia del objeto del Ejercicio 11 como <kw>static</kw> y
	  verifique que, debido a eso, el enlazador es incapaz de encontrarla.
	</para>
      </listitem>
      <listitem>
	<para>
	  Declare una función en un archivo de cabecera. Defina la
	  función en un archivo <filename>cpp</filename> y llámela
	  desde <function>main()</function> en un segundo archivo
	  <filename>cpp</filename>. Compile y verifique que
	  funciona. Ahora cambie la definición de la función de forma
	  que sea <kw>static</kw> y verifique que el enlazador no
	  puede encontrarla.
	</para>
      </listitem>
      <listitem>
	<para>
	  Modifique <filename>Volatile.cpp</filename> del Capítulo 8
	  para hacer que <function>comm::isr()</function> funcione
	  realmente como una rutina de servicio de
	  interrupción. Pista: una rutina de servicio de interrupción
	  no toma ningún argumento.
	</para>
      </listitem>

    <!--
    15. Write and compile a simple program that uses the auto and
    register keywords.

    16. Create a header file containing a namespace. Inside the
    namespace create several function declarations. Now create a second
    header file that includes the first one and continúes the namespace,
    adding several more function declarations. Now create a cpp file
    that includes the second header file. Alias your namespace to
    another (shorter) name. Inside a function definition, call one of
    your functions using scope resolution. Inside a separate function
    definition, write a using directive to introduce your namespace into
    that function scope, and show that you don't need scope resolution
    to call the functions from your namespace.
      -->
      <listitem>
	<para>
	  Escriba y compile un único programa que utilice las palabras
	  clave <kw>auto</kw> y <kw>register</kw>.
	</para>
      </listitem>
      <listitem>
	<para>
	  Cree un archivo de cabecera que contenga un espacio de
	  nombres. Dentro del espacio de nombres cree varias
	  declaraciones de funciones. Cree ahora un segundo archivo de
	  cabecera que incluya el primero y continúe el espacio de
	  nombres, añadiendo varias declaraciones de funciones
	  más. Cree ahora un archivo <filename>cpp</filename> que
	  incluya el segundo archivo de cabecera. Cambie su espacio de
	  nombres a otro nombre (más corto). Dentro de una definición
	  de función, llame a una de sus funciones utilizando la
	  resolución de ámbito. Dentro de una definición de función
	  separada, escriba una directiva <kw>using</kw> para
	  introducir su espacio de nombres en el ámbito de esa
	  función, y demuestre que no necesita utilizar la resolución
	  de ámbito para llamar a las funciones desde su espacio de
	  nombres.
	</para>
      </listitem>

      <!--
    17. Create a header file with an unnamed namespace. Include the
    header in two separate cpp files and show that an unnamed space is
    unique for each translation unit.

    18. Using the header file from Exercise 17, show that the names in
    an unnamed namespace are automatically available in a translation
    unit without qualification.

    19. Modify FriendInjection.cpp to add a definition for the friend
        function and to call the function inside main( ).

    20. In Arithmetic.cpp, demonstrate that the using directive does not
    extend outside the function in which the directive was made.
    -->
      <listitem>
	<para>
	  Cree un archivo de cabecera con un espacio de nombres sin
	  nombre. Incluya la cabecera en dos archivos
	  <filename>cpp</filename> diferentes y demuestre que un
	  espacio sin nombre es único para cada :unidad de traducción.
	</para>
      </listitem>
      <listitem>
	<para>
	  Utilizando el archivo de cabecera del Ejercicio 17,
	  demuestre que los nombres de un espacio de nombres sin
	  nombre están disponibles automáticamente en una :unidad de
	  traducción sin calificación.
	</para>
      </listitem>
      <listitem>
	<para>
	  Modifique <filename>FriendInjection.cpp</filename> para
	  añadir una definición para la función amiga y para llamar a
	  la función desde <function>main()</function>.
	</para>
      </listitem>
      <listitem>
	<para>
	  En <filename>Arithmetic.cpp</filename>, demuestre que la
	  directiva <kw>using</kw> no se extiende fuera de la función en
	  la que fue creada.
    	</para>
      </listitem>

    <!-- 21. Repair the problem in OverridingAmbiguity.cpp, first with
    scope resolution, then instead with a using declaration that forces
    the compiler to choose one of the identical function names.

    22. In two header files, create two namespaces, each containing a
    class (with all inline definitions) with a name identical to that in
    the other namespace. Create a cpp file that includes both header
    files. Create a function, and inside the function use the using
    directive to introduce both namespaces. Try creating an object of
    the class and see what happens. Make the using directives global
    (outside of the function) to see if it makes any difference. Repair
    the problem using scope resolution, and create objects of both
    classes.

    23. Repair the problem in Exercise 22 with a using declaration that
    forces the compiler to choose one of the identical class names.
      -->

      <listitem>
	<para>
	  Repare el problema de
	  <filename>OverridingAmbiguity.cpp</filename>, primero con
	  resolución de ámbito y luego, con una declaración
	  <kw>using</kw> que fuerce al compilador a escojer uno de los
	  nombres de función idénticos.
    	</para>
      </listitem>
      <listitem>
	<para>
	  En dos archivos de cabecera, cree dos espacios de nombres,
	  cada uno conteniendo una clase (con todas las definiciones
	  <kw>inline</kw>) con idéntico nombre que el del otro espacio
	  de nombres. Cree un archivo <filename>cpp</filename> que
	  incluya ambos archivos. Cree una función y, dentro de la
	  función, utilice la directiva <kw>using</kw> para introducir
	  ambos espacios de nombres. Pruebe a crear un objeto de la
	  clase y vea que sucede. Haga las directivas <kw>using</kw>
	  globales (fuera de la función) para ver si existe alguna
	  diferencia. Repare el problema usando la resolución de
	  ámbito, y cree objetos de ambas clases.
	</para>
      </listitem>
      <listitem>
	<para>
	  Repare el problema del Ejercicio 22 con una declaración
	  <kw>using</kw> que fuerce al compilador a escojer uno de los
	  nombres de clase idénticos.
	</para>
      </listitem>

      <!--
    24. Extract the namespace declarations in BobsSuperDuperLibrary.cpp
    and UnnamedNamespaces.cpp and put them in separate header files,
    giving the unnamed namespace a name in the process. In a third
    header file create a new namespace that combines the elements of the
    other two namespaces with using declarations. In main( ), introduce
    your new namespace with a using directive and access all the
    elements of your namespace.

    25. Create a header file that includes <string> and <iostream> but
    does not use any using directives or using declarations. Add
    include guards" as you've seen in the header files in this
    book. Create a class with all inline functions that contains a
    string member, with a constructor that initializes that string from
    its argument and a print( ) function that displays the
    string. Create a cpp file and exercise your class in main( ).

    26. Create a class containing a static double and long. Write a
    static member function that prints out the values.  -->

      <listitem>
	<para>
	  Extraiga las declaraciones de espacios de nombres de
	  <filename>BobsSuperDuperLibrary.cpp</filename> y
	  <filename>UnnamedNamespaces.cpp</filename> y póngalos en
	  archivos separados, dando un nombre al espacio de nombres
	  sin nombre en el proceso. En un tercer archivo de cabecera,
	  cree un nuevo espacio de nombres que combine los elementos
	  de los otros dos espacios de nombres con declaraciones
	  <kw>using</kw>. En <function>main()</function>, introduzca
	  su nuevo espacio de nombres con una directiva <kw>using</kw>
	  y acceda a todos los elementos de su espacio de nombres.
	</para>
      </listitem>
      <listitem>
	<para>
	  Cree un archivo de cabecera que incluya
	  <filename>&lt;string></filename> y
	  <filename>&lt;iostream></filename> pero que no use ninguna
	  directiva <kw>using</kw> ni ninguna declaración
	  <kw>using</kw>. Añada guardas de inclusión como ha visto en
	  los archivos de cabecera del libro. Cree una clase con todas
	  las funciones <kw>inline</kw> que muestre por pantalla el
	  <type>string</type>. Cree un archivo
	  <filename>cpp</filename> y ejercite su clase en
	  <function>main()</function>.
	</para>
      </listitem>
      <listitem>
	<para>
	  Cree una clase que contenga un <type>static double</type> y
	  <type>long</type>. Escriba un método estático que imprima
	  los valores.
   	</para>
      </listitem>


	<!-- 27. Create a class containing an int, a constructor that
    initializes the int from its argument, and a print( ) function to
    display the int. Now create a second class that contains a static
    object of the first one. Add a static member function that calls the
    static object's print( ) function. Exercise your class in
    main( ).

    28. Create a class containing both a const and a non-const static
    array of int. Write static methods to print out the arrays. Exercise
    your class in main( ).
      -->
      <listitem>
	<para>
	  Cree una clase que contenga un <type>int</type>, un
	  constructor que inicialice el <type>int</type> con su
	  argumento, y una función <function>print()</function> que
	  muestre por pantalla el <type>int</type>. Cree ahora una
	  segunda clase que contenga un objeto estático de la
	  primera. Añada un método estático que llame a la función
	  <function>print()</function> del objeto estático.  Ejercitu
	  su clase en <function>main()</function>.
	</para>
      </listitem>
      <listitem>
	<para>
	  Cree una clase que contenga un array estático de
	  <type>int</type> constante y otro no constante. Escriba
	  métodos estáticos que impriman los arrays. Experimente con su clase
	  en <function>main()</function>.
	</para>
      </listitem>

      <!--
    29. Create a class containing a string, with a constructor that
    initializes the string from its argument, and a print( ) function to
    display the string. Create another class that contains both const
    and non-const static arrays of objects of the first class, and
    static methods to print out these arrays. Exercise this second class
    in main( ).

      30. Create a struct that contains an int and a default constructor
    that initializes the int to zero. Make this struct local to a
    function. Inside that function, create an array of objects of your
    struct and demonstrate that each int in the array has automatically
    been initialized to zero.

    31. Create a class that represents a printer connection, and that
    only allows you to have one printer.  -->
      <listitem>
	<para>
	  Cree una clase que contenga un <type>string</type>, con un
	  constructor que inicialice el <type>string</type> a partir
	  de su argumento, y una función <function>print()</function>
	  que imprima el <type>string</type>. Cree otra clase que
	  contenga un array estático, tanto constante como no
	  constante, de objetos de la primera clase, y métodos
	  estáticos para imprimir dichos arrays. Experimente con la
	  segunda clase en <function>main()</function>.
	</para>
      </listitem>
      <listitem>
	<para>
	  Cree una <kw>struct</kw> que contenga un <type>int</type> y
	  un constructor por defecto que inicialice el
	  <type>int</type> a cero.  Haga ese <kw>struct</kw> local a
	  una función. Dentro de dicha función, cree un array de
	  objetos de su <kw>struct</kw> y demuestre que cada
	  <type>int</type> del array ha sido inicializado a cero
	  automáticamente.
	</para>
      </listitem>
      <listitem>
	<para>
	  Cree una clase que represente una conexión a impresora, y que
	  sólo le permita tener una impresora.
	</para>
      </listitem>


    <!-- 32. In a header file, create a class Mirror that contains two
    data members: a pointer to a Mirror object and a bool. Give it two
    constructors: the default constructor initializes the bool to true
    and the Mirror pointer to zero. The second constructor takes as an
    argument a pointer to a Mirror object, which it assigns to the
    object's internal pointer; it sets the bool to false. Add a member
    function test( ): if the object's pointer is nonzero, it returns the
    value of test( ) called through the pointer. If the pointer is zero,
    it returns the bool. Now create five cpp files, each of which
    includes the Mirror header. The first cpp file defines a global
    Mirror object using the default constructor. The second file
    declares the object in the first file as extern, and defines a
    global Mirror object using the second constructor, with a pointer to
    the first object. Keep doing this until you reach the last file,
    which will also contain a global object definition. In that file,
    main( ) should call the test( ) function and report the result. If
    the result is true, find out how to change the linking order for
    your linker and change it until the result is false.

    33. Repair the problem in Exercise 32 using technique one shown in
        this book.

    34. Repair the problem in Exercise 32 using technique two shown in
        this book.

    35. Without including a header file, declare the function puts( )
        from the Standard C Library. Call this function from main( ).
        -->

      <listitem>
	<para>
	  En un archivo de cabecera, cree una clase
	  <classname>Mirror</classname> que contiene dos atributos:
	  un puntero a un objeto <classname>Mirror</classname> y un
	  <type>bool</type>. Déle dos constructores: el constructor
	  por defecto inicializa el <type>bool</type> a <kw>true</kw>
	  y el puntero a <classname>Mirror</classname> a cero. El
	  segundo constructor toma como argumento un puntero a un
	  objeto <classname>Mirror</classname>, que asigna al puntero
	  interno del objeto; pone el <type>bool</type> a
	  <kw>false</kw>. Añada un método <function>test()</function>:
	  si el puntero del objeto es distinto de cero, devuelve el
	  valor de <function>test()</function> llamado a través del
	  puntero. Si el puntero es cero, devuelve el
	  <type>bool</type>. Cree ahora cinco archivos
	  <filename>cpp</filename>, cada uno incluyendo la cabecera
	  <classname>Mirror</classname>. El primer archivo
	  <filename>cpp</filename> define un objeto
	  <classname>Mirror</classname> global utilizando el
	  constructor por defecto. El segundo archivo declara el
	  objeto del primer archivo como <kw>extern</kw>, y define un
	  objeto <classname>Mirror</classname> global utilizando el
	  segundo constructor, con un puntero al primer objeto. Siga
	  haciendo lo mismo hasta que llegue al último archivo, que
	  también contendrá una definición de objeto global. En este
	  archivo, <function>main()</function> debe llamar a la
	  función <function>test()</function> e informar del
	  resultado. Si el resultado es <kw>true</kw>, encuentre la
	  forma de cambiar el orden de enlazado de su enlazador y
	  cámbielo hasta que el resultado sea <kw>false</kw>.
	</para>
      </listitem>
      <listitem>
	<para>
	  Repare el problema del Ejercicio 32 utilizando la técnica uno
          mostrada en este libro.
      	</para>
      </listitem>
      <listitem>
	<para>
	  Repare el problema del Ejercicio 32 utilizando la técnica dos
	  mostrada en este libro.
	</para>
      </listitem>
      <listitem>
	<para>
	  Sin incluir ningún archivo de cabecera, declare la función
	  <function>puts()</function> de la Librería Estándar de C.
	  Llame a esa función desde <function>main()</function>.
	</para>
      </listitem>
    </orderedlist>
  </sect1>
</chapter>