Π§ΠΈΡ‚Π°ΠΉΡ‚Π΅ ΠΊΠ½ΠΈΠ³ΠΈ ΠΎΠ½Π»Π°ΠΉΠ½ Π½Π° Bookidrom.ru! БСсплатныС ΠΊΠ½ΠΈΠ³ΠΈ Π² ΠΎΠ΄Π½ΠΎΠΌ ΠΊΠ»ΠΈΠΊΠ΅

Π§ΠΈΡ‚Π°Ρ‚ΡŒ ΠΎΠ½Π»Π°ΠΉΠ½ Β«Π‘Ρ‚Π°Π½Π΄Π°Ρ€Ρ‚Ρ‹ программирования Π½Π° Π‘++. 101 ΠΏΡ€Π°Π²ΠΈΠ»ΠΎ ΠΈ рСкомСндация». Π‘Ρ‚Ρ€Π°Π½ΠΈΡ†Π° 54

Автор Π“Π΅Ρ€Π± Π‘Π°Ρ‚Ρ‚Π΅Ρ€

ΠŸΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠ΅, ΠΎΡ‚ΠΌΠ΅Π½ΡΡŽΡ‰Π΅Π΅ const, ΠΌΠΎΠΆΠ΅Ρ‚ ΠΎΠΊΠ°Π·Π°Ρ‚ΡŒΡΡ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΡ‹ΠΌ для Π²Ρ‹Π·ΠΎΠ²Π° Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ API, Π½Π΅ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½ΠΎ ΡƒΠΊΠ°Π·Ρ‹Π²Π°ΡŽΡ‰Π΅ΠΉ ΠΊΠΎΠ½ΡΡ‚Π°Π½Ρ‚Π½ΠΎΡΡ‚ΡŒ (см. Ρ€Π΅ΠΊΠΎΠΌΠ΅Π½Π΄Π°Ρ†ΠΈΡŽ 15). Оно Ρ‚Π°ΠΊΠΆΠ΅ ΠΏΠΎΠ»Π΅Π·Π½ΠΎ, ΠΊΠΎΠ³Π΄Π° функция, которая Π΄ΠΎΠ»ΠΆΠ½Π° ΠΏΠΎΠ»ΡƒΡ‡Π°Ρ‚ΡŒ ΠΈ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Ρ‚ΡŒ ссылку ΠΎΠ΄Π½ΠΎΠ³ΠΎ ΠΈ Ρ‚ΠΎΠ³ΠΎ ΠΆΠ΅ Ρ‚ΠΈΠΏΠ°, ΠΈΠΌΠ΅Π΅Ρ‚ ΠΊΠ°ΠΊ ΠΊΠΎΠ½ΡΡ‚Π°Π½Ρ‚Π½ΡƒΡŽ, Ρ‚Π°ΠΊ ΠΈ Π½Π΅ΠΊΠΎΠ½ΡΡ‚Π°Π½Ρ‚Π½ΡƒΡŽ ΠΏΠ΅Ρ€Π΅Π³Ρ€ΡƒΠ·ΠΊΠΈ, ΠΏΡ€ΠΈΡ‡Π΅ΠΌ ΠΎΠ΄Π½Π° ΠΈΠ· Π½ΠΈΡ… Π²Ρ‹Π·Ρ‹Π²Π°Π΅Ρ‚ Π΄Ρ€ΡƒΠ³ΡƒΡŽ:

const Object& f(const Object&);


Object& f(Object& obj {

 const Object& ref = obj;

 return const_cast<Object&>(f(ref)); // ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠ΅

}                                    // Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅ΠΌΠΎΠ³ΠΎ Ρ‚ΠΈΠΏΠ°

Бсылки

[Dewhurst03] Β§32, Β§40 β€’ [Sutter00] Β§44

95. НС ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠ΅ Ρ‚ΠΈΠΏΠΎΠ² Π² стилС Π‘

РСзюмС

Возраст Π½Π΅ всСгда ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚ ΠΌΡƒΠ΄Ρ€ΠΎΡΡ‚ΡŒ. Π‘Ρ‚Π°Ρ€ΠΎΠ΅ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠ΅ Ρ‚ΠΈΠΏΠΎΠ² Π² стилС Π‘ ΠΈΠΌΠ΅Π΅Ρ‚ Ρ€Π°Π·Π»ΠΈΡ‡Π½ΡƒΡŽ (ΠΈ часто ΠΎΠΏΠ°ΡΠ½ΡƒΡŽ) сСмантику Π² зависимости ΠΎΡ‚ контСкста, ΡΠΏΡ€ΡΡ‚Π°Π½Π½ΡƒΡŽ Π·Π° Π΅Π΄ΠΈΠ½Ρ‹ΠΌ синтаксисом. Π—Π°ΠΌΠ΅Π½Π° прСобразования Ρ‚ΠΈΠΏΠΎΠ² Π² стилС Π‘ прСобразованиями Π‘++ ΠΏΠΎΠΌΠΎΠΆΠ΅Ρ‚ Π·Π°Ρ‰ΠΈΡ‚ΠΈΡ‚ΡŒΡΡ ΠΎΡ‚ Π½Π΅ΠΎΠΆΠΈΠ΄Π°Π½Π½Ρ‹Ρ… ошибок.

ΠžΠ±ΡΡƒΠΆΠ΄Π΅Π½ΠΈΠ΅

Одна ΠΈΠ· ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌ, связанных с ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠ΅ΠΌ Ρ‚ΠΈΠΏΠΎΠ² Π² стилС Π‘, Π·Π°ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ΡΡ Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ ΠΎΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ ΠΎΠ΄ΠΈΠ½ ΠΈ Ρ‚ΠΎΡ‚ ΠΆΠ΅ синтаксис для выполнСния нСсколько Ρ€Π°Π·Π½Ρ‹Ρ… Π²Π΅Ρ‰Π΅ΠΉ, Π² зависимости ΠΎΡ‚ Ρ‚Π°ΠΊΠΈΡ… ΠΌΠ΅Π»ΠΎΡ‡Π΅ΠΉ, ΠΊΠ°ΠΊ, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, ΠΊΠ°ΠΊΠΈΠ΅ ΠΈΠΌΠ΅Π½Π½ΠΎ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΎΡ‡Π½Ρ‹Π΅ Ρ„Π°ΠΉΠ»Ρ‹ Π²ΠΊΠ»ΡŽΡ‡Π΅Π½Ρ‹ ΠΏΡ€ΠΈ ΠΏΠΎΠΌΠΎΡ‰ΠΈ Π΄ΠΈΡ€Π΅ΠΊΡ‚ΠΈΠ²Ρ‹ #include. ΠŸΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΡ Ρ‚ΠΈΠΏΠΎΠ² Π² стилС Π‘++, сохраняя ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½ΡƒΡŽ ΠΎΠΏΠ°ΡΠ½ΠΎΡΡ‚ΡŒ, ΠΏΡ€ΠΈΡΡƒΡ‰ΡƒΡŽ прСобразованиям Π²ΠΎΠΎΠ±Ρ‰Π΅, ΠΈΠΌΠ΅ΡŽΡ‚ Ρ‡Π΅Ρ‚ΠΊΠΎ Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚ΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎΠ΅ ΠΏΡ€Π΅Π΄Π½Π°Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅, ΠΈΡ… Π»Π΅Π³ΠΊΠΎ Π½Π°ΠΉΡ‚ΠΈ, дольшС ΠΏΠΈΡΠ°Ρ‚ΡŒ (Ρ‡Ρ‚ΠΎ Π΄Π°Π΅Ρ‚ врСмя Π΄Π²Π°ΠΆΠ΄Ρ‹ ΠΏΠΎΠ΄ΡƒΠΌΠ°Ρ‚ΡŒ ΠΏΡ€ΠΈ ΠΈΡ… использовании), ΠΈ Π½Π΅ ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡŽΡ‚ Π½Π΅Π·Π°ΠΌΠ΅Ρ‚Π½ΠΎ Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒ опасноС ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠ΅ reinterpret_cast (см. Ρ€Π΅ΠΊΠΎΠΌΠ΅Π½Π΄Π°Ρ†ΠΈΡŽ 92).

Рассмотрим ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΉ ΠΊΠΎΠ΄, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ Derived β€” ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄Π½Ρ‹ΠΉ ΠΎΡ‚ Π±Π°Π·ΠΎΠ²ΠΎΠ³ΠΎ класса Base:

extern void Fun(Derived*);


void Gun(Base* pb) {

// Π‘ΡƒΠ΄Π΅ΠΌ ΡΡ‡ΠΈΡ‚Π°Ρ‚ΡŒ, Ρ‡Ρ‚ΠΎ функция Gun Π·Π½Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ pb Π²

// Π΄Π΅ΠΉΡΡ‚Π²ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ ΡƒΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚ Π½Π° ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ Ρ‚ΠΈΠΏΠ° Derived ΠΈ

// Ρ…ΠΎΡ‡Π΅Ρ‚ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ Π΅Π³ΠΎ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Fun

Derived* pd = (Derived*)pb; // ΠŸΠ»ΠΎΡ…ΠΎ: ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠ΅

Fun(pd);                    // Π² стилС Π‘

}

Если функция Gun ΠΈΠΌΠ΅Π΅Ρ‚ доступ ΠΊ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΡŽ Derived (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, ΠΏΡ€ΠΈ Π²ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠΈ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΎΡ‡Π½ΠΎΠ³ΠΎ Ρ„Π°ΠΉΠ»Π° derived.h), Ρ‚ΠΎ компилятор ΠΈΠΌΠ΅Π΅Ρ‚ всю Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΡƒΡŽ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ ΠΎ Ρ€Π°Π·ΠΌΠ΅Ρ‰Π΅Π½ΠΈΠΈ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒ всС Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΡ‹Π΅ дСйствия ΠΏΠΎ ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚ΠΈΡ€ΠΎΠ²ΠΊΠ΅ указатСля ΠΏΡ€ΠΈ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠΈ ΠΎΡ‚ Base ΠΊ Derived. Но Ссли Π°Π²Ρ‚ΠΎΡ€ Gun Π·Π°Π±Ρ‹Π» Π²ΠΊΠ»ΡŽΡ‡ΠΈΡ‚ΡŒ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΉ Ρ„Π°ΠΉΠ» опрСдСлСния, ΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Gun Π²ΠΈΠ΄Π½ΠΎ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΏΡ€Π΅Π΄Π²Π°Ρ€ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΠ΅ объявлСниС класса Derived, Ρ‚ΠΎ компилятор Π±ΡƒΠ΄Π΅Ρ‚ ΠΏΠΎΠ»Π°Π³Π°Ρ‚ΡŒ, Ρ‡Ρ‚ΠΎ Base ΠΈ Derived β€” нСсвязанныС Ρ‚ΠΈΠΏΡ‹, ΠΈ ΠΈΠ½Ρ‚Π΅Ρ€ΠΏΡ€Π΅Ρ‚ΠΈΡ€ΡƒΠ΅Ρ‚ Π±ΠΈΡ‚Ρ‹ указатСля Base* ΠΊΠ°ΠΊ Π±ΠΈΡ‚Ρ‹ указатСля Derived*, Π½Π΅ дСлая Π½ΠΈΠΊΠ°ΠΊΠΈΡ… ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ†ΠΈΠΉ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΌΠΎΠ³ΡƒΡ‚ Π΄ΠΈΠΊΡ‚ΠΎΠ²Π°Ρ‚ΡŒΡΡ Ρ€Π°Π·ΠΌΠ΅Ρ‰Π΅Π½ΠΈΠ΅ΠΌ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π° Π² памяти!

ΠšΠΎΡ€ΠΎΡ‚ΠΊΠΎ говоря, Ссли Π²Ρ‹ Π·Π°Π±ΡƒΠ΄Π΅Ρ‚Π΅ Π²ΠΊΠ»ΡŽΡ‡ΠΈΡ‚ΡŒ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ класса, Ρ‚ΠΎ ваш ΠΊΠΎΠ΄ ΠΌΠΎΠΆΠ΅Ρ‚ Π°Π²Π°Ρ€ΠΈΠΉΠ½ΠΎ Π·Π°Π²Π΅Ρ€ΡˆΠΈΡ‚ΡŒΡΡ Π±Π΅Π· Π²ΠΈΠ΄ΠΈΠΌΡ‹Ρ… ΠΏΡ€ΠΈΡ‡ΠΈΠ½, ΠΏΡ€ΠΈ Ρ‚ΠΎΠΌ Ρ‡Ρ‚ΠΎ компилятор Π½Π΅ сообщил Π½ΠΈ ΠΎΠ± ΠΎΠ΄Π½ΠΎΠΉ ошибкС. Избавимся ΠΎΡ‚ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡ‹ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΌ способом:

extern void Fun(Derived*);


void Gun(Base* pb) {

 // Если ΠΌΡ‹ Π³Π°Ρ€Π°Π½Ρ‚ΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎ Π·Π½Π°Π΅ΠΌ, Ρ‡Ρ‚ΠΎ pb Π½Π° самом Π΄Π΅Π»Π΅

 // ΡƒΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚ Π½Π° ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ Ρ‚ΠΈΠΏΠ° Derived:


 // ΠŸΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠ΅ Π² стилС Π‘++

 Derived* pd = static_cast<Derived*>(pb);


 // Π’ ΠΏΡ€ΠΎΡ‚ΠΈΠ²Π½ΠΎΠΌ случаС слСдуСт ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ

 // = dynamic_cast<Derived*>(pb);

 Fun(pd);

}

Π’Π΅ΠΏΠ΅Ρ€ΡŒ, Ссли Ρƒ компилятора нСдостаточно статичСской ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΠΈ ΠΎΠ± ΠΎΡ‚Π½ΠΎΡˆΠ΅Π½ΠΈΡΡ… ΠΌΠ΅ΠΆΠ΄Ρƒ Base ΠΈ Derived, ΠΎΠ½ Π²Ρ‹Π²Π΅Π΄Π΅Ρ‚ сообщСниС ΠΎΠ± ошибкС, вмСсто Ρ‚ΠΎΠ³ΠΎ Ρ‡Ρ‚ΠΎΠ±Ρ‹ автоматичСски ΠΏΡ€ΠΈΠΌΠ΅Π½ΠΈΡ‚ΡŒ ΠΏΠΎΠ±ΠΈΡ‚ΠΎΠ²ΠΎΠ΅ (ΠΈ ΠΏΠΎΡ‚Π΅Π½Ρ†ΠΈΠ°Π»ΡŒΠ½ΠΎ опасноС) ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠ΅ reinterpret_cast (см. Ρ€Π΅ΠΊΠΎΠΌΠ΅Π½Π΄Π°Ρ†ΠΈΡŽ 92).

ΠŸΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΡ Π² стилС Π‘++ ΠΌΠΎΠ³ΡƒΡ‚ Π·Π°Ρ‰ΠΈΡ‚ΠΈΡ‚ΡŒ ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½ΠΎΡΡ‚ΡŒ вашСго ΠΊΠΎΠ΄Π° Π² процСссС ΡΠ²ΠΎΠ»ΡŽΡ†ΠΈΠΈ систСмы. ΠŸΡƒΡΡ‚ΡŒ, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, Ρƒ вас Π΅ΡΡ‚ΡŒ иСрархия с ΠΊΠΎΡ€Π½Π΅ΠΌ Π² Employee, ΠΈ Π²Π°ΠΌ Π½Π°Π΄ΠΎ ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈΡ‚ΡŒ ΡƒΠ½ΠΈΠΊΠ°Π»ΡŒΠ½Ρ‹ΠΉ ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ ID для ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π° Employee. Π’Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈΡ‚ΡŒ ID ΠΊΠ°ΠΊ ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ Π½Π° сам ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ Employee. Π£ΠΊΠ°Π·Π°Ρ‚Π΅Π»ΠΈ ΠΎΠ΄Π½ΠΎΠ·Π½Π°Ρ‡Π½ΠΎ ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΡ†ΠΈΡ€ΡƒΡŽΡ‚ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Ρ‹, Π½Π° ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΡƒΠΊΠ°Π·Ρ‹Π²Π°ΡŽΡ‚, ΠΈ ΠΌΠΎΠ³ΡƒΡ‚ ΡΡ€Π°Π²Π½ΠΈΠ²Π°Ρ‚ΡŒΡΡ Π½Π° равСнство Π΄Ρ€ΡƒΠ³ Π΄Ρ€ΡƒΠ³Ρƒ β€” Ρ‡Ρ‚ΠΎ Π² точности Ρ‚ΠΎ, Ρ‡Ρ‚ΠΎ Π½Π°ΠΌ ΠΈ Π½Π°Π΄ΠΎ. Π˜Ρ‚Π°ΠΊ, запишСм:

typedef Employee* EmployeeID;


Employee& Fetch(EmployeeID id) {

 return *id;

}

ΠŸΡƒΡΡ‚ΡŒ Π²Ρ‹ ΠΊΠΎΠ΄ΠΈΡ€ΡƒΠ΅Ρ‚Π΅ Ρ‡Π°ΡΡ‚ΡŒ систСмы с Π΄Π°Π½Π½Ρ‹ΠΌ Π΄ΠΈΠ·Π°ΠΉΠ½ΠΎΠΌ. ΠŸΡƒΡΡ‚ΡŒ ΠΏΠΎΠ·ΠΆΠ΅ Π²Π°ΠΌ трСбуСтся ΡΠΎΡ…Ρ€Π°Π½ΡΡ‚ΡŒ ваши записи Π² рСляционной Π±Π°Π·Π΅ Π΄Π°Π½Π½Ρ‹Ρ…. ΠŸΠΎΠ½ΡΡ‚Π½ΠΎ, Ρ‡Ρ‚ΠΎ сохранСниС ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»Π΅ΠΉ β€” Π½Π΅ Ρ‚ΠΎ, Ρ‡Ρ‚ΠΎ Π²Π°ΠΌ трСбуСтся. Π’ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π΅ Π²Ρ‹ измСняСтС Π΄ΠΈΠ·Π°ΠΉΠ½ Ρ‚Π°ΠΊ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ ΠΈΠΌΠ΅Π» ΡƒΠ½ΠΈΠΊΠ°Π»ΡŒΠ½Ρ‹ΠΉ цСлочислСнный ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€. Π’ΠΎΠ³Π΄Π° цСлочислСнный ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ ΠΌΠΎΠΆΠ΅Ρ‚ Ρ…Ρ€Π°Π½ΠΈΡ‚ΡŒΡΡ Π² Π±Π°Π·Π΅ Π΄Π°Π½Π½Ρ‹Ρ…, Π° Ρ…ΡΡˆ-Ρ‚Π°Π±Π»ΠΈΡ†Π° ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ°Π΅Ρ‚ ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€Ρ‹ Π½Π° ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Ρ‹ Employee. Π’Π΅ΠΏΠ΅Ρ€ΡŒ typedef выглядит ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ:

typedef int EmployeeID;


Employee& Fetch( EmployeeID id ) {

 return employeeTable_.lookup(id);

}

Π­Ρ‚ΠΎ ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½Ρ‹ΠΉ Π΄ΠΈΠ·Π°ΠΉΠ½, ΠΈ Π²Ρ‹ ΠΎΠΆΠΈΠ΄Π°Π΅Ρ‚Π΅, Ρ‡Ρ‚ΠΎ любоС Π½Π΅Π²Π΅Ρ€Π½ΠΎΠ΅ ΡƒΠΏΠΎΡ‚Ρ€Π΅Π±Π»Π΅Π½ΠΈΠ΅ EmployeeID Π΄ΠΎΠ»ΠΆΠ½ΠΎ привСсти ΠΊ ошибкС Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ компиляции. Π’Π°ΠΊ ΠΈ получаСтся, Π·Π° ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ΠΌ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅Π³ΠΎ нСбольшого Ρ„Ρ€Π°Π³ΠΌΠ΅Π½Ρ‚Π°:

void TooCoolToUseNewCasts(EmployeeID id) {

 Secretary* pSecretary = (Secretary*)id; // ΠŸΠ»ΠΎΡ…ΠΎ:

 // ...                                  // ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠ΅ Π² стилС Π‘

}

ΠŸΡ€ΠΈ использовании старой инструкции typedef ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠ΅ Π² стилС Π‘ выполняСт static_cast, ΠΏΡ€ΠΈ Π½ΠΎΠ²ΠΎΠΉ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ reinterpret_cast с Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΌ Ρ†Π΅Π»Ρ‹ΠΌ числом, Ρ‡Ρ‚ΠΎ даст Π½Π°ΠΌ Π½Π΅ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½ΠΎΠ΅ ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ (см. Ρ€Π΅ΠΊΠΎΠΌΠ΅Π½Π΄Π°Ρ†ΠΈΡŽ 92).

ΠŸΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΡ Π² стилС Π‘++ ΠΏΡ€ΠΎΡ‰Π΅ ΠΈΡΠΊΠ°Ρ‚ΡŒ Π² исходных тСкстах ΠΏΡ€ΠΈ ΠΏΠΎΠΌΠΎΡ‰ΠΈ автоматичСского инструмСнтария Π½Π°ΠΏΠΎΠ΄ΠΎΠ±ΠΈΠ΅ grep (Π½ΠΎ Π½ΠΈΠΊΠ°ΠΊΠΎΠ΅ рСгулярноС Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ grep Π½Π΅ ΠΏΠΎΠ·Π²ΠΎΠ»ΠΈΡ‚ Π²Ρ‹Π»ΠΎΠ²ΠΈΡ‚ΡŒ синтаксис прСобразования Ρ‚ΠΈΠΏΠΎΠ² Π² стилС Π‘). ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ прСобразования ΠΎΡ‡Π΅Π½ΡŒ опасны (Π² особСнности static_cast для ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»Π΅ΠΉ ΠΈ reinterpret_cast; см. Ρ€Π΅ΠΊΠΎΠΌΠ΅Π½Π΄Π°Ρ†ΠΈΡŽ 92), использованиС Π°Π²Ρ‚ΠΎΠΌΠ°Ρ‚ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎΠ³ΠΎ инструмСнтария для ΠΈΡ… отслСТивания β€” нСплохая идСя.

Бсылки

[Dewhurst03] Β§40 β€’ [Meyers96] Β§2 β€’ [Stroustrup00] Β§15.4.5 β€’ [Sutter00] Β§44

96. НС примСняйтС memcpy ΠΈΠ»ΠΈ memcmp ΠΊ Π½Π΅-POD Ρ‚ΠΈΠΏΠ°ΠΌ

РСзюмС

НС Ρ€Π°Π±ΠΎΡ‚Π°ΠΉΡ‚Π΅ рСнтгСновским Π°ΠΏΠΏΠ°Ρ€Π°Ρ‚ΠΎΠΌ (см. Ρ€Π΅ΠΊΠΎΠΌΠ΅Π½Π΄Π°Ρ†ΠΈΡŽ 91). НС ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ memcpy ΠΈ memcmp для копирования ΠΈΠ»ΠΈ сравнСния Ρ‡Π΅Π³ΠΎ-Π»ΠΈΠ±ΠΎ структурированного Π±ΠΎΠ»Π΅Π΅, Ρ‡Π΅ΠΌ обычная ΠΏΠ°ΠΌΡΡ‚ΡŒ.

ΠžΠ±ΡΡƒΠΆΠ΄Π΅Π½ΠΈΠ΅

Π€ΡƒΠ½ΠΊΡ†ΠΈΠΈ memcpy ΠΈ memcmp Π½Π°Ρ€ΡƒΡˆΠ°ΡŽΡ‚ систСму Ρ‚ΠΈΠΏΠΎΠ². Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ memcpy для копирования ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠ² β€” это Ρ‚ΠΎ ΠΆΠ΅, Ρ‡Ρ‚ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ксСрокс для копирования Π΄Π΅Π½Π΅Π³, Π° ΡΡ€Π°Π²Π½ΠΈΠ²Π°Ρ‚ΡŒ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Ρ‹ ΠΏΡ€ΠΈ ΠΏΠΎΠΌΠΎΡ‰ΠΈ memcmp β€” Ρ‚ΠΎ ΠΆΠ΅, Ρ‡Ρ‚ΠΎ ΡΡ€Π°Π²Π½ΠΈΠ²Π°Ρ‚ΡŒ Π΄Π²ΡƒΡ… Π»Π΅ΠΎΠΏΠ°Ρ€Π΄ΠΎΠ² ΠΏΠΎ количСству пятСн. Π˜Π½ΡΡ‚Ρ€ΡƒΠΌΠ΅Π½Ρ‚Ρ‹ ΠΈ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ ΠΌΠΎΠ³ΡƒΡ‚ ΠΊΠ°Π·Π°Ρ‚ΡŒΡΡ подходящими для выполнСния Ρ€Π°Π±ΠΎΡ‚Ρ‹, Π½ΠΎ ΠΎΠ½ΠΈ слишком Π³Ρ€ΡƒΠ±Ρ‹ для Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ Π΅Π΅ ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎ.

ΠžΠ±ΡŠΠ΅ΠΊΡ‚Ρ‹ Π‘++ ΠΏΡ€Π΅Π΄Π½Π°Π·Π½Π°Ρ‡Π΅Π½Ρ‹ для сокрытия Π΄Π°Π½Π½Ρ‹Ρ… (Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ, Π½Π°ΠΈΠ±ΠΎΠ»Π΅Π΅ Π²Π°ΠΆΠ½Ρ‹ΠΉ ΠΏΡ€ΠΈΠ½Ρ†ΠΈΠΏ Π² Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠ΅ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ½ΠΎΠ³ΠΎ обСспСчСния; см. Ρ€Π΅ΠΊΠΎΠΌΠ΅Π½Π΄Π°Ρ†ΠΈΡŽ 11). ΠžΠ±ΡŠΠ΅ΠΊΡ‚Ρ‹ ΡΠΊΡ€Ρ‹Π²Π°ΡŽΡ‚ Π΄Π°Π½Π½Ρ‹Π΅ (см. Ρ€Π΅ΠΊΠΎΠΌΠ΅Π½Π΄Π°Ρ†ΠΈΡŽ 41) ΠΈ ΠΏΡ€Π΅Π΄ΠΎΡΡ‚Π°Π²Π»ΡΡŽΡ‚ Ρ‚ΠΎΡ‡Π½Ρ‹Π΅ абстракции для копирования этих Π΄Π°Π½Π½Ρ‹Ρ… посрСдством конструкторов ΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€ΠΎΠ² присваивания (см. Ρ€Π΅ΠΊΠΎΠΌΠ΅Π½Π΄Π°Ρ†ΠΈΠΈ с 52 ΠΏΠΎ 55). ΠŸΡ€ΠΎΠΉΡ‚ΠΈΡΡŒ ΠΏΠΎ Π½ΠΈΠΌ Π³Ρ€ΡƒΠ±Ρ‹ΠΌ инструмСнтом Ρ‚ΠΈΠΏΠ° memcpy β€” ΡΠ΅Ρ€ΡŒΠ΅Π·Π½ΠΎΠ΅ Π½Π°Ρ€ΡƒΡˆΠ΅Π½ΠΈΠ΅ ΠΏΡ€ΠΈΠ½Ρ†ΠΈΠΏΠ° сокрытия ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΠΈ, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ Π·Π°Ρ‡Π°ΡΡ‚ΡƒΡŽ ΠΏΡ€ΠΈΠ²ΠΎΠ΄ΠΈΡ‚ ΠΊ ΡƒΡ‚Π΅Ρ‡ΠΊΠ°ΠΌ памяти ΠΈ рСсурсов (Π² Π»ΡƒΡ‡ΡˆΠ΅ΠΌ случаС), Π°Π²Π°Ρ€ΠΈΠΉΠ½ΠΎΠΌΡƒ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡŽ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ (Π² случаС ΠΏΠΎΡ…ΡƒΠΆΠ΅) ΠΈΠ»ΠΈ Π½Π΅ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½ΠΎΠΌΡƒ повСдСнию (Π² самом Ρ…ΡƒΠ΄ΡˆΠ΅ΠΌ случаС). НапримСр:

{

 // Π‘ΠΎΠ·Π΄Π°Π΅ΠΌ Π΄Π²Π° int Π² памяти

 shared_ptr<int> p1(new int), p2(new int);


 memcpy(&p1, &p2, sizeof(p1)); // Π’Π°ΠΊ Π΄Π΅Π»Π°Ρ‚ΡŒ нСльзя!!!

} // Π£Ρ‚Π΅Ρ‡ΠΊΠ° памяти: p2 Π½ΠΈΠΊΠΎΠ³Π΄Π° Π½Π΅ удаляСтся

  // ΠΏΠΎΠ²Ρ€Π΅ΠΆΠ΄Π΅Π½ΠΈΠ΅ памяти: p1 удаляСтся Π΄Π²Π°ΠΆΠ΄Ρ‹

НСвСрноС ΠΏΡ€ΠΈΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ memcpy ΠΌΠΎΠΆΠ΅Ρ‚ Π²Π»ΠΈΡΡ‚ΡŒ Π½Π° Ρ‚Π°ΠΊΠΈΠ΅ Ρ„ΡƒΠ½Π΄Π°ΠΌΠ΅Π½Ρ‚Π°Π»ΡŒΠ½Ρ‹Π΅ свойства, ΠΊΠ°ΠΊ Ρ‚ΠΈΠΏ ΠΈ ΡΡƒΡ‰Π½ΠΎΡΡ‚ΡŒ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°. ΠšΠΎΠΌΠΏΠΈΠ»ΡΡ‚ΠΎΡ€Ρ‹ часто Π΄ΠΎΠ±Π°Π²Π»ΡΡŽΡ‚ ΠΊ ΠΏΠΎΠ»ΠΈΠΌΠΎΡ€Ρ„Π½Ρ‹ΠΌ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°ΠΌ скрытыС Π΄Π°Π½Π½Ρ‹Π΅ (Ρ‚Π°ΠΊ Π½Π°Π·Ρ‹Π²Π°Π΅ΠΌΡ‹ΠΉ ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ Π½Π° Π²ΠΈΡ€Ρ‚ΡƒΠ°Π»ΡŒΠ½ΡƒΡŽ Ρ‚Π°Π±Π»ΠΈΡ†Ρƒ), ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΡΡŽΡ‚ ΡΡƒΡ‰Π½ΠΎΡΡ‚ΡŒ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π° Π²ΠΎ врСмя выполнСния ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹. Π’ случаС мноТСствСнного наслСдования Π² ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π΅ содСрТится нСсколько Ρ‚Π°ΠΊΠΈΡ… Ρ‚Π°Π±Π»ΠΈΡ†, с Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹ΠΌΠΈ смСщСниями Π²Π½ΡƒΡ‚Ρ€ΠΈ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°, ΠΈ Π±ΠΎΠ»ΡŒΡˆΠΈΠ½ΡΡ‚Π²ΠΎ Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΉ Π΄ΠΎΠ±Π°Π²Π»ΡΡŽΡ‚ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ Π²Π½ΡƒΡ‚Ρ€Π΅Π½Π½ΠΈΠ΅ ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΠΈ ΠΏΡ€ΠΈ Π²ΠΈΡ€Ρ‚ΡƒΠ°Π»ΡŒΠ½ΠΎΠΌ наслСдовании. ΠŸΡ€ΠΈ ΠΎΠ±Ρ‹Ρ‡Π½ΠΎΠΌ использовании компилятор ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Π΅Ρ‚ ΠΌΠ΅Ρ€Ρ‹ для ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½ΠΎΠ³ΠΎ управлСния всСми скрытыми полями; ΠΏΡ€ΠΈΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ memcpy способно внСсти Π² этот ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ хаос.

Аналогично, функция memcmp β€” нСподходящий инструмСнт для сравнСния Ρ‡Π΅Π³ΠΎ-Ρ‚ΠΎ Π±ΠΎΠ»Π΅Π΅ слоТного, Ρ‡Π΅ΠΌ просто Π½Π°Π±ΠΎΡ€Ρ‹ Π±ΠΈΡ‚ΠΎΠ². Иногда эта функция Π΄Π΅Π»Π°Π΅Ρ‚ слишком ΠΌΠ°Π»ΠΎ (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, сравнСниС строк Π² стилС Π‘ β€” Π½Π΅ Ρ‚ΠΎ ΠΆΠ΅, Ρ‡Ρ‚ΠΎ ΠΈ сравнСниС ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»Π΅ΠΉ, ΠΏΡ€ΠΈ ΠΏΠΎΠΌΠΎΡ‰ΠΈ ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… эти строки Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½Ρ‹). А ΠΈΠ½ΠΎΠ³Π΄Π°, ΠΊΠ°ΠΊ это Π½ΠΈ ΠΏΠ°Ρ€Π°Π΄ΠΎΠΊΡΠ°Π»ΡŒΠ½ΠΎ, memcmp Π΄Π΅Π»Π°Π΅Ρ‚ слишком ΠΌΠ½ΠΎΠ³ΠΎ (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, memcmp ΠΌΠΎΠΆΠ΅Ρ‚ ΡΠΎΠ²Π΅Ρ€ΡˆΠ΅Π½Π½ΠΎ напрасно ΡΡ€Π°Π²Π½ΠΈΠ²Π°Ρ‚ΡŒ Π±Π°ΠΉΡ‚Ρ‹, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π½Π΅ ΡΠ²Π»ΡΡŽΡ‚ΡΡ Ρ‡Π°ΡΡ‚ΡŒΡŽ состояния ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°, Ρ‚Π°ΠΊΠΈΠ΅ ΠΊΠ°ΠΊ Π·Π°ΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΠΈ, вставлСнныС компилятором для выравнивания). Π’ ΠΎΠ±ΠΎΠΈΡ… случаях Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ сравнСния оказываСтся Π½Π΅Π²Π΅Ρ€Π½Ρ‹ΠΌ.