home *** CD-ROM | disk | FTP | other *** search
/ Chip 2002 September / Chip_2002-09_cd1.bin / obsahy / Chip_txt / txt / 116-118.txt < prev    next >
Text File  |  2002-08-08  |  9KB  |  102 lines

  1. Jazyky C# a C++
  2. Kdy₧ je n∞co jinak...
  3. Programovacφ jazyk C# je natolik podobn² jazyku C++, ₧e to programßtora zvyklΘho na C++ snadno svede k nepozornosti. V²sledkem pak m∙₧e b²t nejedno nemilΘ p°ekvapenφ, nebo¥ n∞kterß pravidla jsou v jazyce C# v²razn∞ odliÜnß. Zde si povÜimneme n∞kolika ·skalφ hrozφcφch kv∙li t∞mto rozdφl∙m p°i prßci s metodami.
  4.  
  5. P°etφ₧enΘ metody
  6. Podobn∞ jako C++, i C# dovoluje p°et∞₧ovat metody. Postup p°i urΦenφ, kterou metodu mß p°ekladaΦ zavolat, je v ka₧dΘm z jazyk∙ pon∞kud jin². To nejspφÜ nikoho nep°ekvapφ, nebo¥ se liÜφ i systΘm jejich datov²ch typ∙. NicmΘn∞ zßkladnφ myÜlenka je v obou jazycφch stejnß: Sestavφ se mno₧ina "kandidßt∙", tedy metod se stejn²m identifikßtorem a se stejn²m poΦtem formßlnφch parametr∙, a mezi nimi se vybere metoda, jejφ₧ signatura (v C++ bychom °ekli prototyp) nejlΘpe odpovφdß typ∙m skuteΦn²ch parametr∙. (O tom budeme hovo°it jako o pravidlu "lepÜφ shody".) Jist∞ vφte, ₧e v C++ nenφ mo₧nΘ rozliÜovat p°etφ₧enΘ metody na zßklad∞ toho, zda se jejich parametry p°edßvajφ hodnotou nebo odkazem. V C# vÜak rozliÜovat p°etφ₧enΘ metody podle zp∙sobu p°edßvßnφ parametr∙ lze, nebo¥ ten je souΦßstφ signatury. To znamenß, ₧e v jednΘ t°φd∞ m∙₧eme mφt vedle sebe nap°. metody
  7.  
  8. void f(int i); // Parametr p°edßvan² hodnotou
  9. void f(ref int i); // Parametr p°edßvan² odkazem
  10. void f(out int i); // V²stupnφ parametr
  11.  
  12. Vysv∞tlenφ, proΦ je to v C# mo₧nΘ, je jednoduchΘ: Modifikßtory ref, resp. out, je₧ oznaΦujφ parametry p°edßvanΘ odkazem, resp. v²stupnφ parametry, zapisujeme takΘ p°ed skuteΦnΘ parametry p°i volßnφ. Chceme-li nap°. zavolat metodu f() a jako v²stupnφ parametr jφ p°edat prom∞nnou x, napφÜeme f(out x);.
  13. V C#, stejn∞ jako v C++, lze definovat takΘ metody s prom∞nn²m poΦtem parametr∙. V C++ k tomu slou₧φ v²pustka (...), v C# modifikßtor params. Tento modifikßtor ovÜem v C# k rozliÜenφ p°etφ₧en²ch metod pou₧φt nelze.
  14.  
  15. Zastφn∞nφ metody
  16. V C#, stejn∞ jako v C++, p°edstavuje t°φda obor viditelnosti identifikßtor∙. Jestli₧e v C++ deklarujeme v odvozenΘ t°φd∞ stejn² identifikßtor jako v p°edkovi, zastφnφme tφm identifikßtor z p°edka; v C# platφ podobnΘ pravidlo pro v∞tÜinu identifikßtor∙, v p°φpad∞ metod je vÜak situace slo₧it∞jÜφ. Ukß₧eme si p°φklad, kdy se v d∙sledku toho program v C# chovß jinak ne₧ analogickß konstrukce v C++.
  17. Nejprve deklarujeme t°φdu A, je₧ bude obsahovat ve°ejn∞ p°φstupnou metodu f() typu void bez parametr∙:
  18.  
  19. class A // C# { public void f(){/* ... */} }
  20.  
  21. (Podobn∞ jako v C++ i v C# platφ, ₧e pokud v n∞jakΘ t°φd∞ nedeklarujeme ₧ßdn² konstruktor, doplnφ do nφ p°ekladaΦ ve°ejn∞ p°φstupn² konstruktor bez parametr∙; proto si m∙₧eme dovolit deklaraci konstruktoru ve t°φd∞ A vynechat.)
  22. Dßle deklarujeme t°φdu B jako potomka t°φdy A. Ve t°φd∞ B deklarujeme op∞t metodu f(), tentokrßt ovÜem s jednφm parametrem typu int:
  23.  
  24. class B: A // C#
  25. { new public void f(int i){} static void Main(string[] args)
  26. {
  27. B b = new B(); b.f(); } }
  28.  
  29. V metod∞ Main() vytvo°φme instanci t°φdy B a zavolßme metodu f() bez parametr∙; v C# to je v po°ßdku, nebo¥ metoda f(int i), deklarovanß ve t°φd∞ B, nenφ zastφn∞na metodou f() deklarovanou v p°edkovi. Na druhΘ stran∞ analogick² program v C++,
  30.  
  31. class A // C++ {public: void f(){} }; class B: public A {public: void f(int i){} }; void main() {
  32. C *b = new B; b->f(); }
  33.  
  34. se nepoda°φ p°elo₧it, nebo¥ p°ekladaΦ ohlßsφ n∞co jako "p°φliÜ mßlo parametr∙ p°i volßnφ metody f()". V C# platφ, ₧e deklarujeme-li v odvozenΘ t°φd∞ metodu s identifikßtorem f, zastφnφme tφm metodu p°edka se stejnou signaturou. Metody se stejn²m identifikßtorem, ale s rozdφlnou signaturou, z∙stanou viditelnΘ.
  35.  
  36. Proto tφm, ₧e jsme ve t°φd∞ B deklarovali metodu f(int i), jsme nezastφnili metodu f()zd∞d∞nou od t°φdy A, nebo¥ se liÜφ jejich signatury.
  37.  
  38. Zd∞d∞nΘ a vlastnφ metody
  39. Z p°edchozφho p°φkladu by se mohlo zdßt, ₧e zd∞d∞nΘ metody majφ v C# stejnΘ postavenφ jako metody definovanΘ v odvozenΘ t°φd∞. To vÜak nenφ pravda; podφvejme se na nßsledujφcφ p°φklad:
  40.  
  41. using System; // C# class A { public void f(int i)
  42. {
  43. Console.WriteLine("A.f(int)");
  44. } }; class B: A { public void f(long i)
  45. {
  46. Console.WriteLine("B.f(long)");
  47. } }class Program { static void Main(string[] args)
  48. {
  49. B b = new B(); b.f('a');
  50. } }
  51.  
  52. V p°edkovi, ve t°φd∞ A, jsme definovali metodu f(int i), zatφmco v potomkovi metodu f(long i). V metod∞ Main() vytvo°φme instanci t°φdy B a zavolßme metodu f() se skuteΦn²m parametrem typu char. (To lze, nebo¥ v C# je stejn∞ jako v C++ k dispozici implicitnφ konverze typu char na celoΦφselnΘ typy.)
  53. Podle pravidla o "lepÜφ shod∞" bychom mohli oΦekßvat, ₧e se zavolß zd∞d∞nß metoda f(int i). V²stup tohoto programu nßs vÜak p°esv∞dΦφ, ₧e se volß metoda f(long i) definovanß v odvozenΘ t°φd∞ B. Stejnß metoda se zavolß i v p°φpad∞, ₧e metodu f() zavolßme p°φkazem b.f(1); i kdy₧ se v tomto p°φpad∞ typ skuteΦnΘho parametru p°esn∞ shoduje s typem formßlnφho parametru zd∞d∞nΘ metody.
  54. Na druhΘ stran∞, zm∞nφme-li deklarace metod f() takto:
  55.  
  56. class A // C# { public void f(long i)
  57. {Console.WriteLine("A.f(long)");} }; class B: A { public void f(short i)
  58. {Console.WriteLine("B.f(short)");} }
  59.  
  60. a zavolßme-li metodu f() p°φkazy
  61.  
  62. int a = 1; b.f(a);
  63.  
  64. zavolß se zd∞d∞nß metoda, nebo¥ konverze typu int na short nem∙₧e v C# prob∞hnout implicitn∞.
  65.  
  66. Modifikßtor new
  67. U₧ jsme si °ekli, ₧e definujeme-li v odvozenΘ t°φd∞ slo₧ku se stejn²m identifikßtorem jako v p°edkovi, zd∞d∞nou slo₧ku zastφnφme. To ve skuteΦnosti nepot°ebujeme p°φliÜ Φasto. Proto zavßdφ jazyk C# modifikßtor new, kter²m p°ekladaΦi vysv∞tlujeme, ₧e nejde o p°eklep a ₧e si zastφn∞nφ zd∞d∞nΘ slo₧ky opravdu p°ejeme.
  68. Vynechßme-li tento modifikßtor, ohlßsφ p°ekladaΦ varovßnφ; podobn∞ to dopadne, uvedeme-li tento modifikßtor v deklaraci, kterß nic nezasti≥uje.
  69. Modifikßtor new nesmφme v C# pou₧φt spolu s modifikßtorem override. M∙₧eme ho vÜak pou₧φt spolu s modifikßtorem virtual, tj. v odvozenΘ t°φd∞ smφme deklarovat nap°. metodu public new virtual void f() {/* ... */} Takovßto deklarace p°eruÜφ hierarchii virtußlnφch metod a znamenß novou implementaci, nezßvislou na implementaci z p°edka. (NejspφÜ nep∙jde o nijak Φasto pou₧φvanou konstrukci, ale n∞jak² d∙vod, proΦ to tv∙rci jazyka zavedli, asi bude.)
  70.  
  71. P°φstupovß prßva
  72. V C++ se p°i vyhledßvßnφ p°etφ₧en²ch metod neuplat≥ujφ p°φstupovß prßva: Nejprve se zjistφ, kterß metoda nejlΘpe odpovφdß typ∙m skuteΦn²ch parametr∙ p°i volßnφ, a pak se urΦφ, zda ji lze zavolat (zda to dovolujφ p°φstupovß prßva). V C# se p°φstupovß prßva uplat≥ujφ u₧ p°i vyhledßvßnφ "kandidßt∙". Podφvejme se na p°φklad: V p°edkovi, ve t°φd∞ A, deklarujeme ve°ejn∞ p°φstupnou metodu f() bez parametr∙. V potomkovi, ve t°φd∞ B, ji zastφnφme chrßn∞nou metodou se stejnou signaturou. Ve t°φd∞
  73.  
  74. Program, v metod∞ Main(), vytvo°φme instanci t°φdy B a zavolßme pro ni metodu f():
  75.  
  76. using System; // C# class A { public void f()
  77. {
  78. Console.WriteLine("A.f");
  79. } }class B: A { new protected void f() {
  80. Console.WriteLine("B.f"); } }class Program { static void Main()
  81. {
  82. B b = new B(); b.f();
  83. } }
  84.  
  85. Tento program zavolß metodu f() zd∞d∞nou po t°φd∞ A. Metoda f(), deklarovanß ve t°φd∞ B, nenφ p°φstupnß, a proto ji p°ekladaΦ p°i v²b∞ru kandidßt∙ nebere v ·vahu. Podφvejme se jeÜt∞ na analogick² program v C++:
  86.  
  87. #include <iostream.h> // C++ class A { public: void f()
  88. { cout << "A.f";
  89. } }; class B: public A { protected: void f()
  90. { cout << "B.f";
  91. } }; void main() {
  92. B *b = new B; b->f(); }
  93.  
  94. Pokus o p°eklad tohoto programu skonΦφ chybou - p°ekladaΦ oznßmφ, ₧e metoda B::f() nenφ dostupnß, nebo¥ p°φstupovß prßva vzal v ·vahu a₧ po urΦenφ metody, kterou je t°eba volat.
  95. Filozofii jazyka C++, pokud jde o aplikaci p°φstupov²ch prßv, lze shrnout do v∞ty, ₧e "zm∞na p°φstupov²ch prßv nesmφ zm∞nit chovßnφ programu". (Tak to formuloval B. Stroustrup v jednΘ z knih o C++.)
  96. Jazyk C# se °φdφ spφÜe filozofiφ "co nenφ p°φstupnΘ, o tom nevφm, to neberu v ·vahu". Zm∞na p°φstupov²ch prßv v tomto jazyce proto m∙₧e vΘst k pom∞rn∞ zßsadnφ zm∞n∞ v chovßnφ programu: V zßvislosti na pou₧itΘm modifikßtoru se budou volat r∙znΘ metody!
  97.  
  98. Nenφ jazyk jako jazyk
  99. Tolik prozatφm k nejmarkantn∞jÜφm odliÜnostem C# a C++, pokud jde o zachßzenφ s metodami. Tφm ovÜem nejsou vyΦerpßna vÜechna nebezpeΦφ vypl²vajφcφ ze shodnΘ Φi podobnΘ syntaxe a rozdφlnΘ sΘmantiky programov²ch konstrukcφ v r∙zn²ch jazycφch. K jazyku C#, v n∞m₧ takovΘ zßm∞ny hrozφ pom∞rn∞ Φasto, a k jeho porovnßnφ s jin²mi programovacφmi jazyky se proto jeÜt∞ n∞kdy vrßtφme.
  100.  
  101. Miroslav Virius, autor@chip.cz
  102.