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

Π§ΠΈΡ‚Π°Ρ‚ΡŒ ΠΎΠ½Π»Π°ΠΉΠ½ Β«Π­Ρ„Ρ„Π΅ΠΊΡ‚ΠΈΠ²Π½ΠΎΠ΅ использованиС C++. 55 Π²Π΅Ρ€Π½Ρ‹Ρ… способов ΡƒΠ»ΡƒΡ‡ΡˆΠΈΡ‚ΡŒ структуру ΠΈ ΠΊΠΎΠ΄ Π²Π°ΡˆΠΈΡ… ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΒ». Π‘Ρ‚Ρ€Π°Π½ΠΈΡ†Π° 29

Автор Π‘ΠΊΠΎΡ‚Ρ‚ ΠœΠ°ΠΉΠ΅Ρ€Ρ

result = oneHalf * 2; // ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎ

result = 2 * oneHalf; // ошибка!


Π­Ρ‚ΠΎ ΠΏΠ»ΠΎΡ…ΠΎΠΉ Π·Π½Π°ΠΊ. Π£ΠΌΠ½ΠΎΠΆΠ΅Π½ΠΈΠ΅ Π΄ΠΎΠ»ΠΆΠ½ΠΎ Π±Ρ‹Ρ‚ΡŒ ΠΊΠΎΠΌΠΌΡƒΡ‚Π°Ρ‚ΠΈΠ²Π½Ρ‹ΠΌ (Π½Π΅ Π·Π°Π²ΠΈΡΠ΅Ρ‚ΡŒ ΠΎΡ‚ порядка сомноТитСлСй), ΠΏΠΎΠΌΠ½ΠΈΡ‚Π΅?

Π˜ΡΡ‚ΠΎΡ‡Π½ΠΈΠΊ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡ‹ становится понятным, Ссли ΠΏΠ΅Ρ€Π΅ΠΏΠΈΡΠ°Ρ‚ΡŒ Π΄Π²Π° послСдних выраТСния Π² Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½ΠΎΠΉ Ρ„ΠΎΡ€ΠΌΠ΅:


result = oneHalf.operator*(2); // ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎ

result = 2.operator*(oneHalf); // ошибка!


ΠžΠ±ΡŠΠ΅ΠΊΡ‚ oneHalf – это экзСмпляр класса, Π²ΠΊΠ»ΡŽΡ‡Π°ΡŽΡ‰Π΅Π³ΠΎ Π² сСбя operator*, поэтому компилятор Π²Ρ‹Π·Ρ‹Π²Π°Π΅Ρ‚ эту Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ. Но с Ρ†Π΅Π»Ρ‹ΠΌ числом 2 Π½Π΅ ассоциирован Π½ΠΈΠΊΠ°ΠΊΠΎΠΉ класс, Π° Π·Π½Π°Ρ‡ΠΈΡ‚, Π½Π΅Ρ‚ для Π½Π΅Π³ΠΎ ΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ operator*. ΠšΠΎΠΌΠΏΠΈΠ»ΡΡ‚ΠΎΡ€ Π±ΡƒΠ΄Π΅Ρ‚ Ρ‚Π°ΠΊΠΆΠ΅ ΠΈΡΠΊΠ°Ρ‚ΡŒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ operator*, Π½Π΅ ΡΠ²Π»ΡΡŽΡ‰ΠΈΠ΅ΡΡ Ρ‡Π»Π΅Π½Π°ΠΌΠΈ класса (Π² Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΌ пространствС ΠΈΠΌΠ΅Π½ ΠΈΠ»ΠΈ Π² глобальной области видимости):


result = operator*(2, oneHalf); // ошибка!


Но Π² Π΄Π°Π½Π½ΠΎΠΌ случаС Π½Π΅Ρ‚ ΠΈ свободной Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ operator*, которая ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Π»Π° Π±Ρ‹ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚Ρ‹ int ΠΈ Rational, поэтому поиск Π·Π°Π²Π΅Ρ€ΡˆΠΈΡ‚ΡΡ Π½ΠΈΡ‡Π΅ΠΌ.

ΠŸΠΎΡΠΌΠΎΡ‚Ρ€ΠΈΠΌ Π΅Ρ‰Π΅ Ρ€Π°Π· Π½Π° ΡƒΡΠΏΠ΅ΡˆΠ½Ρ‹ΠΉ Π²Ρ‹Π·ΠΎΠ². Π’ΠΈΠ΄ΠΈΡ‚Π΅, Ρ‡Ρ‚ΠΎ Π²Ρ‚ΠΎΡ€ΠΎΠΉ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ – Ρ†Π΅Π»ΠΎΠ΅ число 2, хотя Rational::operator* ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Π΅Ρ‚ Π² качСствС Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚Π° ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ Rational. Π§Ρ‚ΠΎ происходит? ΠŸΠΎΡ‡Π΅ΠΌΡƒ 2 Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ Π² ΠΎΠ΄Π½ΠΎΠΉ ΠΏΠΎΠ·ΠΈΡ†ΠΈΠΈ ΠΈ Π½Π΅ Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ Π² Π΄Ρ€ΡƒΠ³ΠΎΠΉ?

ΠŸΡ€ΠΎΠΈΡΡ…ΠΎΠ΄ΠΈΡ‚ нСявноС ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠ΅ Ρ‚ΠΈΠΏΠ°. ΠšΠΎΠΌΠΏΠΈΠ»ΡΡ‚ΠΎΡ€ Π·Π½Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ Π²Ρ‹ ΠΏΠ΅Ρ€Π΅Π΄Π°Π»ΠΈ int, Π° функция Ρ‚Ρ€Π΅Π±ΡƒΠ΅Ρ‚ Rational, Π½ΠΎ ΠΎΠ½ Ρ‚Π°ΠΊΠΆΠ΅ Π·Π½Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ подходящий ΠΎΠ±ΡŠΠ΅ΠΊΡ‚, Ссли Π²Ρ‹Π·Π²Π°Ρ‚ΡŒ конструктор Rational c ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½Ρ‹ΠΌ Π²Π°ΠΌΠΈ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚ΠΎΠΌ int. Π’Π°ΠΊ ΠΎΠ½ ΠΈ поступаСт. Π˜Π½Ρ‹ΠΌΠΈ словами, компилятор Ρ‚Ρ€Π°ΠΊΡ‚ΡƒΠ΅Ρ‚ ΠΏΠΎΠΊΠ°Π·Π°Π½Π½Ρ‹ΠΉ Π²Ρ‹ΡˆΠ΅ Π²Ρ‹Π·ΠΎΠ², ΠΊΠ°ΠΊ Ссли Π±Ρ‹ ΠΎΠ½ Π±Ρ‹Π» написан ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π½ΠΎ Ρ‚Π°ΠΊ:


const Rational temp(2); // ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ Π²Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹ΠΉ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ Rational ΠΈΠ· 2

result = oneHalf * temp; // Ρ‚ΠΎ ΠΆΠ΅, Ρ‡Ρ‚ΠΎ oneHalf.operator*(temp);


ΠšΠΎΠ½Π΅Ρ‡Π½ΠΎ, компилятор Π΄Π΅Π»Π°Π΅Ρ‚ это Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΏΠΎΡ‚ΠΎΠΌΡƒ, Ρ‡Ρ‚ΠΎ Π΅ΡΡ‚ΡŒ конструктор, ΠΎΠ±ΡŠΡΠ²Π»Π΅Π½Π½Ρ‹ΠΉ Π±Π΅Π· ΠΊΠ²Π°Π»ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€Π° explicit. Если Π±Ρ‹ ΠΊΠ²Π°Π»ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ explicit присутствовал, Ρ‚ΠΎ Π½ΠΈ ΠΎΠ΄Π½ΠΎ ΠΈΠ· ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΡ… ΠΏΡ€Π΅Π΄Π»ΠΎΠΆΠ΅Π½ΠΈΠΉ Π½Π΅ ΡΠΊΠΎΠΌΠΏΠΈΠ»ΠΈΡ€ΠΎΠ²Π°Π»ΠΎΡΡŒ Π±Ρ‹:


result = oneHalf * 2; // ошибка! (ΠΏΡ€ΠΈ Π½Π°Π»ΠΈΡ‡ΠΈΠΈ explicit-конструктора):

// Π½Π΅Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Ρ‚ΡŒ 2 Π² Ratinal

result = 2 * oneHalf; // Ρ‚Π° ΠΆΠ΅ ошибка, Ρ‚Π° ΠΆΠ΅ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ°


Π‘ΠΎ смСшанной Π°Ρ€ΠΈΡ„ΠΌΠ΅Ρ‚ΠΈΠΊΠΎΠΉ ΠΏΡ€ΠΈ Ρ‚Π°ΠΊΠΎΠΌ ΠΏΠΎΠ΄Ρ…ΠΎΠ΄Π΅ придСтся Ρ€Π°ΡΠΏΡ€ΠΎΡΡ‚ΠΈΡ‚ΡŒΡΡ, Π½ΠΎ, ΠΏΠΎ ΠΊΡ€Π°ΠΉΠ½Π΅ΠΉ ΠΌΠ΅Ρ€Π΅, Ρ‚Π°ΠΊΠΎΠ΅ ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ Π½Π΅ΠΏΡ€ΠΎΡ‚ΠΈΠ²ΠΎΡ€Π΅Ρ‡ΠΈΠ²ΠΎ.

Π’Π°ΡˆΠ° Ρ†Π΅Π»ΡŒ, ΠΎΠ΄Π½Π°ΠΊΠΎ, β€“ ΠΎΠ±Π΅ΡΠΏΠ΅Ρ‡ΠΈΡ‚ΡŒ ΠΈ ΡΠΎΠ³Π»Π°ΡΠΎΠ²Π°Π½Π½ΠΎΡΡ‚ΡŒ, ΠΈ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΡƒ смСшанной Π°Ρ€ΠΈΡ„ΠΌΠ΅Ρ‚ΠΈΠΊΠΈ, Ρ‚ΠΎ Π΅ΡΡ‚ΡŒ Π½ΡƒΠΆΠ½ΠΎ Π½Π°ΠΉΡ‚ΠΈ Ρ‚Π°ΠΊΠΎΠ΅ Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅, ΠΏΡ€ΠΈ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ ΠΎΠ±Π° прСдлоТСния ΠΊΠΎΠΌΠΏΠΈΠ»ΠΈΡ€ΡƒΡŽΡ‚ΡΡ. Π­Ρ‚ΠΎ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ нас ΠΊ вопросу ΠΎ Ρ‚ΠΎΠΌ, ΠΏΠΎΡ‡Π΅ΠΌΡƒ Π΄Π°ΠΆΠ΅ ΠΏΡ€ΠΈ Π½Π°Π»ΠΈΡ‡ΠΈΠΈ explicit-конструктора Π² классС Rational ΠΎΠ΄Π½ΠΎ ΠΈΠ· Π½ΠΈΡ… компилируСтся, Π° Π΄Ρ€ΡƒΠ³ΠΎΠ΅ – Π½Π΅Ρ‚:


result = oneHalf * 2; // ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎ (ΠΏΡ€ΠΈ Π½Π΅ explicit-конструкторС)

result = 2 * oneHalf; // ошибка! (Π΄Π°ΠΆΠ΅ ΠΏΡ€ΠΈ Π½Π΅ explicit-конструкторС)


ΠžΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚ΡΡ, Ρ‡Ρ‚ΠΎ ΠΊ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Π°ΠΌ ΠΏΡ€ΠΈΠΌΠ΅Π½ΠΈΠΌΡ‹ нСявныС прСобразования, Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Ссли ΠΎΠ½ΠΈ пСрСчислСны Π² спискС ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠ². НСявный ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€, ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΉ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Ρƒ, Ρ‡ΡŒΡ функция-Ρ‡Π»Π΅Π½ вызываСтся (Ρ‚ΠΎΡ‚, Π½Π° ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΡƒΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚ this), Π½ΠΈΠΊΠΎΠ³Π΄Π° Π½Π΅ подвСргаСтся нСявному ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΡŽ. Π’ΠΎΡ‚ ΠΏΠΎΡ‡Π΅ΠΌΡƒ ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ Π²Ρ‹Π·ΠΎΠ² компилируСтся, Π° Π²Ρ‚ΠΎΡ€ΠΎΠΉ – Π½Π΅Ρ‚. Π’ ΠΏΠ΅Ρ€Π²ΠΎΠΌ случаС ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ ΡƒΠΊΠ°Π·Π°Π½ Π² спискС ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠ² Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ, Π° Π²ΠΎ Π²Ρ‚ΠΎΡ€ΠΎΠΌ – Π½Π΅Ρ‚.

Однако Π²Π°ΠΌ Ρ…ΠΎΡ‚Π΅Π»ΠΎΡΡŒ Π±Ρ‹ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ ΠΏΠΎΠ»Π½ΠΎΡ†Π΅Π½Π½ΡƒΡŽ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΡƒ смСшанной Π°Ρ€ΠΈΡ„ΠΌΠ΅Ρ‚ΠΈΠΊΠΈ, ΠΈ Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ ясно, ΠΊΠ°ΠΊ Π΅Π΅ ΠΎΠ±Π΅ΡΠΏΠ΅Ρ‡ΠΈΡ‚ΡŒ: Π½ΡƒΠΆΠ΅Π½ operator* Π² Π²ΠΈΠ΄Π΅ свободной Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ, Ρ‚ΠΎΠ³Π΄Π° компилятор смоТСт Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒ нСявноС ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠ΅ всСх Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚ΠΎΠ²:


class Rational {

... // Π½Π΅ содСрТит operator*

};

const Rational operator*(const Rational& lhs, // Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ свободная функция

const Rational& rhs)

{

return Rational(lhs.numerator() * rhs.numerator(),

lhs.denominator() * rhs.denominator());

}

Rational oneFourth(1, 4);

Rational result;

result = oneFourth * 2; // ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎ

result = 2 * oneFourth; // ΡƒΡ€Π°, Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚!


Π­Ρ‚ΠΎ ΠΌΠΎΠΆΠ½ΠΎ Π±Ρ‹Π»ΠΎ Π±Ρ‹ Π½Π°Π·Π²Π°Ρ‚ΡŒ счастливым ΠΊΠΎΠ½Ρ†ΠΎΠΌ, Ссли Π±Ρ‹ Π½Π΅ ΠΎΠ΄Π½ΠΎ Β«Π½ΠΎΒ». Π”ΠΎΠ»ΠΆΠ΅Π½ Π»ΠΈ operator* Π±Ρ‹Ρ‚ΡŒ Π΄Ρ€ΡƒΠ³ΠΎΠΌ класса Rational?

Π’ Π΄Π°Π½Π½ΠΎΠΌ случаС ΠΎΡ‚Π²Π΅Ρ‚ΠΎΠΌ Π±ΡƒΠ΄Π΅Ρ‚ Β«Π½Π΅Ρ‚Β», ΠΏΠΎΡ‚ΠΎΠΌΡƒ Ρ‡Ρ‚ΠΎ operator* ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½ ΠΏΠΎΠ»Π½ΠΎΡΡ‚ΡŒΡŽ Π² Ρ‚Π΅Ρ€ΠΌΠΈΠ½Π°Ρ… ΠΎΡ‚ΠΊΡ€Ρ‹Ρ‚ΠΎΠ³ΠΎ интСрфСйса Rational. ΠŸΡ€ΠΈΠ²Π΅Π΄Π΅Π½Π½Ρ‹ΠΉ Π²Ρ‹ΡˆΠ΅ ΠΊΠΎΠ΄ ΠΏΠΎΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚, ΠΊΠ°ΠΊ это ΠΌΠΎΠΆΠ½ΠΎ ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ. И ΠΌΡ‹ ΠΏΡ€ΠΈΡ…ΠΎΠ΄ΠΈΠΌ ΠΊ Π²Π°ΠΆΠ½ΠΎΠΌΡƒ Π²Ρ‹Π²ΠΎΠ΄Ρƒ: ΠΏΡ€ΠΎΡ‚ΠΈΠ²ΠΎΠΏΠΎΠ»ΠΎΠΆΠ½ΠΎΡΡ‚ΡŒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ-Ρ‡Π»Π΅Π½Π° являСтся свободная функция, Π° функция – Π΄Ρ€ΡƒΠ³ класса. МногиС программисты Π½Π° C++ ΠΏΠΎΠ»Π°Π³Π°ΡŽΡ‚, Ρ‡Ρ‚ΠΎ Ρ€Π°Π· функция ΠΈΠΌΠ΅Π΅Ρ‚ ΠΎΡ‚Π½ΠΎΡˆΠ΅Π½ΠΈΠ΅ ΠΊ классу ΠΈ Π½Π΅ Π΄ΠΎΠ»ΠΆΠ½Π° Π±Ρ‹Ρ‚ΡŒ Π΅Π³ΠΎ Ρ‡Π»Π΅Π½ΠΎΠΌ (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, ΠΈΠ·-Π·Π° нСобходимости ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Ρ‹Π²Π°Ρ‚ΡŒ Ρ‚ΠΈΠΏΡ‹ всСх Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚ΠΎΠ²), Ρ‚ΠΎ ΠΎΠ½Π° Π΄ΠΎΠ»ΠΆΠ½Π° Π±Ρ‹Ρ‚ΡŒ Π΄Ρ€ΡƒΠ³ΠΎΠΌ. Π­Ρ‚ΠΎΡ‚ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ ΠΏΠΎΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ Ρ‚Π°ΠΊΠΎΠ΅ ΠΏΡ€Π΅Π΄ΠΏΠΎΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ Π½Π΅ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎ. Если Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΠΈΠ·Π±Π΅ΠΆΠ°Ρ‚ΡŒ назначСния Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π΄Ρ€ΡƒΠ³ΠΎΠΌ класса, Ρ‚ΠΎ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ Ρ‚Π°ΠΊ ΠΈ ΠΏΠΎΡΡ‚ΡƒΠΏΠΈΡ‚ΡŒ, ΠΏΠΎΡ‚ΠΎΠΌΡƒ Ρ‡Ρ‚ΠΎ, ΠΊΠ°ΠΊ ΠΈ Π² Ρ€Π΅Π°Π»ΡŒΠ½ΠΎΠΉ ΠΆΠΈΠ·Π½ΠΈ, Π΄Ρ€ΡƒΠ·ΡŒΡ часто Π΄ΠΎΡΡ‚Π°Π²Π»ΡΡŽΡ‚ большС Ρ…Π»ΠΎΠΏΠΎΡ‚, Ρ‡Π΅ΠΌ Ρ…ΠΎΡ‚Π΅Π»ΠΎΡΡŒ Π±Ρ‹. ΠšΠΎΠ½Π΅Ρ‡Π½ΠΎ, ΠΈΠ½ΠΎΠ³Π΄Π° ΠΎΡ‚Π½ΠΎΡˆΠ΅Π½ΠΈΡ друТСствСнности ΠΎΠΏΡ€Π°Π²Π΄Π°Π½Ρ‹, Π½ΠΎ Ρ„Π°ΠΊΡ‚ остаСтся Ρ„Π°ΠΊΡ‚ΠΎΠΌ: Ссли функция Π½Π΅ Π΄ΠΎΠ»ΠΆΠ½Π° Π±Ρ‹Ρ‚ΡŒ Ρ‡Π»Π΅Π½ΠΎΠΌ, это Π½Π΅ ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚ автоматичСски, Ρ‡Ρ‚ΠΎ ΠΎΠ½Π° Π΄ΠΎΠ»ΠΆΠ½Π° Π±Ρ‹Ρ‚ΡŒ Π΄Ρ€ΡƒΠ³ΠΎΠΌ.

Π‘ΠΊΠ°Π·Π°Π½Π½ΠΎΠ΅ Π²Ρ‹ΡˆΠ΅ ΠΏΡ€Π°Π²Π΄Π°, ΠΈ Π½ΠΈΡ‡Π΅Π³ΠΎ, ΠΊΡ€ΠΎΠΌΠ΅ ΠΏΡ€Π°Π²Π΄Ρ‹, Π½ΠΎ это Π½Π΅ вся ΠΏΡ€Π°Π²Π΄Π°. Когда Π²Ρ‹ ΠΏΠ΅Ρ€Π΅Ρ…ΠΎΠ΄ΠΈΡ‚Π΅ ΠΎΡ‚ Β«ΠžΠ±ΡŠΠ΅ΠΊΡ‚Π½ΠΎ-ΠΎΡ€ΠΈΠ΅Π½Ρ‚ΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎΠ³ΠΎ C++Β» ΠΊ Β«C++ с шаблонами» (см. ΠΏΡ€Π°Π²ΠΈΠ»ΠΎ 1) ΠΈ ΠΏΡ€Π΅Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚Π΅ Rational ΠΈΠ· класса Π² шаблон класса, Ρ‚ΠΎ Π²ΡΡ‚ΡƒΠΏΠ°ΡŽΡ‚ Π² силу Π½ΠΎΠ²Ρ‹Π΅ Ρ„Π°ΠΊΡ‚ΠΎΡ€Ρ‹, Π½ΠΎΠ²Ρ‹Π΅ способы ΠΈΡ… ΡƒΡ‡Π΅Ρ‚Π°, ΠΈ ΠΏΠΎΡΠ²Π»ΡΡŽΡ‚ΡΡ Π½Π΅ΠΎΠΆΠΈΠ΄Π°Π½Π½Ρ‹Π΅ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π½Ρ‹Π΅ Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ. ВсС это являСтся Ρ‚Π΅ΠΌΠΎΠΉ ΠΏΡ€Π°Π²ΠΈΠ»Π° 46.

Π§Ρ‚ΠΎ слСдуСт ΠΏΠΎΠΌΠ½ΠΈΡ‚ΡŒ

β€’ Если ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠ΅ Ρ‚ΠΈΠΏΠΎΠ² Π΄ΠΎΠ»ΠΆΠ½ΠΎ Π±Ρ‹Ρ‚ΡŒ ΠΏΡ€ΠΈΠΌΠ΅Π½ΠΈΠΌΠΎ ΠΊΠΎ всСм ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Π°ΠΌ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ (Π²ΠΊΠ»ΡŽΡ‡Π°Ρ ΠΈ скрытый ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ this), Ρ‚ΠΎ функция Π½Π΅ Π΄ΠΎΠ»ΠΆΠ½Π° Π±Ρ‹Ρ‚ΡŒ Ρ‡Π»Π΅Π½ΠΎΠΌ класса.

ΠŸΡ€Π°Π²ΠΈΠ»ΠΎ 25: ΠŸΠΎΠ΄ΡƒΠΌΠ°ΠΉΡ‚Π΅ ΠΎ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠ΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ swap, Π½Π΅ Π²ΠΎΠ·Π±ΡƒΠΆΠ΄Π°ΡŽΡ‰Π΅ΠΉ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠΉ

swap – интСрСсная функция. Π˜Π·Π½Π°Ρ‡Π°Π»ΡŒΠ½ΠΎ ΠΎΠ½Π° появилась Π² Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ΅ STL ΠΈ с Ρ‚Π΅Ρ… ΠΏΠΎΡ€ стала, Π²ΠΎ-ΠΏΠ΅Ρ€Π²Ρ‹Ρ…, основой для написания ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌ, бСзопасных Π² смыслС ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠΉ (см. ΠΏΡ€Π°Π²ΠΈΠ»ΠΎ 29), Π° Π²ΠΎ-Π²Ρ‚ΠΎΡ€Ρ‹Ρ…, ΠΎΠ±Ρ‰ΠΈΠΌ ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌΠΎΠΌ Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ Π·Π°Π΄Π°Ρ‡ΠΈ ΠΈ присваивания самому сСбС (см. ΠΏΡ€Π°Π²ΠΈΠ»ΠΎ 11). Π Π°Π· ΡƒΠΆ swap Π½Π°ΡΡ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΏΠΎΠ»Π΅Π·Π½Π°, Ρ‚ΠΎ Π²Π°ΠΆΠ½ΠΎ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π΅Π΅ ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎ, Π½ΠΎ Ρ€ΡƒΠΊΠ° ΠΎΠ± Ρ€ΡƒΠΊΡƒ с особой Π²Π°ΠΆΠ½ΠΎΡΡ‚ΡŒΡŽ ΠΈΠ΄ΡƒΡ‚ ΠΈ особыС слоТности. Π’ этом ΠΏΡ€Π°Π²ΠΈΠ»Π΅ ΠΌΡ‹ исслСдуСм, Ρ‡Ρ‚ΠΎ ΠΎΠ½ΠΈ собой ΠΏΡ€Π΅Π΄ΡΡ‚Π°Π²Π»ΡΡŽΡ‚ ΠΈ ΠΊΠ°ΠΊ с Π½ΠΈΠΌΠΈ Π±ΠΎΡ€ΠΎΡ‚ΡŒΡΡ.

Π§Ρ‚ΠΎΠ±Ρ‹ ΠΎΠ±ΠΌΠ΅Π½ΡΡ‚ΡŒ (swap) значСния Π΄Π²ΡƒΡ… ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠ², Π½ΡƒΠΆΠ½ΠΎ ΠΏΡ€ΠΈΡΠ²ΠΎΠΈΡ‚ΡŒ ΠΊΠ°ΠΆΠ΄ΠΎΠΌΡƒ ΠΈΠ· Π½ΠΈΡ… Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ Π΄Ρ€ΡƒΠ³ΠΎΠ³ΠΎ. По ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ Ρ‚Π°ΠΊΠΎΠΉ ΠΎΠ±ΠΌΠ΅Π½ осущСствляСт стандартный Π°Π»Π³ΠΎΡ€ΠΈΡ‚ΠΌ swap. Π•Π³ΠΎ типичная рСализация Π½Π΅ расходится с вашими оТиданиями:


namespace std {

template <typename T> // типичная рСализация std::swap

void swap(T& a, T& b) // мСняСт мСстами значСния a ΠΈ b

{

T temp(a);

a = b;

b = temp;

}

}


Коль скоро Ρ‚ΠΈΠΏ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅Ρ‚ ΠΊΠΎΠΏΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ (с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ конструктора копирования ΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€Π° присваивания), рСализация swap ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ позволяСт ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°ΠΌ этого Ρ‚ΠΈΠΏΠ° ΠΎΠ±ΠΌΠ΅Π½ΠΈΠ²Π°Ρ‚ΡŒΡΡ значСниями Π±Π΅Π· всяких Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹Ρ… усилий с вашСй стороны.

Бтандартная рСализация swap, ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ, Π½Π΅ ΠΏΡ€ΠΈΠ²Π΅Π΄Π΅Ρ‚ вас Π² восторг. Она Π²ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ ΠΊΠΎΠΏΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ Ρ‚Ρ€Π΅Ρ… ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠ²: a Π² temp, b Π² a ΠΈ temp – Π² b. Для Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… Ρ‚ΠΈΠΏΠΎΠ² Π½ΠΈ ΠΎΠ΄Π½Π° ΠΈΠ· этих опСрация Π² Π΄Π΅ΠΉΡΡ‚Π²ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ Π½Π΅ являСтся Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎΠΉ. Для Ρ‚Π°ΠΊΠΈΡ… Ρ‚ΠΈΠΏΠΎΠ² swap ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ – быстрый ΠΏΡƒΡ‚ΡŒ Π½Π° ΠΌΠ΅Π΄Π»Π΅Π½Π½ΡƒΡŽ Π΄ΠΎΡ€ΠΎΠΆΠΊΡƒ.

Π‘Ρ€Π΅Π΄ΠΈ Ρ‚Π°ΠΊΠΈΡ… Ρ‚ΠΈΠΏΠΎΠ² сразу стоит Π²Ρ‹Π΄Π΅Π»ΠΈΡ‚ΡŒ Ρ‚Π΅, Ρ‡Ρ‚ΠΎ состоят Π² основном ΠΈΠ· ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»Π΅ΠΉ Π½Π° Π΄Ρ€ΡƒΠ³ΠΎΠΉ Ρ‚ΠΈΠΏ, содСрТащий Ρ€Π΅Π°Π»ΡŒΠ½Ρ‹Π΅ Π΄Π°Π½Π½Ρ‹Π΅. ΠžΠ±Ρ‰Π΅Π΅ Π½Π°Π·Π²Π°Π½ΠΈΠ΅ для Ρ‚Π°ΠΊΠΈΡ… ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π½Ρ‹Ρ… Ρ€Π΅ΡˆΠ΅Π½ΠΈΠΉ: Β«ΠΈΠ΄ΠΈΠΎΠΌΠ° pimplΒ» (pointer to implementation – ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ Π½Π° Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΡŽ – см. ΠΏΡ€Π°Π²ΠΈΠ»ΠΎ 31). Π‘ΠΏΡ€ΠΎΠ΅ΠΊΡ‚ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹ΠΉ Ρ‚Π°ΠΊ класс Widget ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ объявлСн ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ:


class WidgetImpl { // класс для Π΄Π°Π½Π½Ρ‹Ρ… Widget

public: // Π΄Π΅Ρ‚Π°Π»ΠΈ нСсущСствСнны

...

private:

int a,b,c; // Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ, ΠΌΠ½ΠΎΠ³ΠΎ Π΄Π°Π½Π½Ρ‹Ρ… –

std::vector<double> v; // ΠΊΠΎΠΏΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ обойдСтся Π΄ΠΎΡ€ΠΎΠ³ΠΎ

...

};

class Widget { // класс, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‰ΠΈΠΉ ΠΈΠ΄ΠΈΠΎΠΌΡƒ pimpl

public:

Widget(const Widget& rhs);

Widget& operator=(const Widget& rhs) // Ρ‡Ρ‚ΠΎΠ± ΡΠΊΠΎΠΏΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Widget, ΠΊΠΎΠΏΠΈΡ€ΡƒΠ΅ΠΌ

{ // Π΅Π³ΠΎ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ WidgetImpl. Π”Π΅Ρ‚Π°Π»ΠΈ

... // Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ operator= ΠΊΠ°ΠΊ Ρ‚Π°ΠΊΠΎΠ²ΠΎΠ³ΠΎ

*pimpl = *(rhs.pimpl); // см. Π² ΠΏΡ€Π°Π²ΠΈΠ»Π°Ρ… 10, 11 ΠΈ 12

...

}

...

private:

WidgetImpl *pimpl; // ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ Π½Π° ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ с Π΄Π°Π½Π½Ρ‹ΠΌΠΈ

}; // этого Widget


Π§Ρ‚ΠΎΠ±Ρ‹ ΠΎΠ±ΠΌΠ΅Π½ΡΡ‚ΡŒ значСния Π΄Π²ΡƒΡ… ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠ² Widget, Π½ΡƒΠΆΠ½ΠΎ лишь ΠΎΠ±ΠΌΠ΅Π½ΡΡ‚ΡŒ значСниями ΠΈΡ… ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΠΈ pimpl, Π½ΠΎ Π°Π»Π³ΠΎΡ€ΠΈΡ‚ΠΌ swap ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ ΠΎΠ± этом Π·Π½Π°Ρ‚ΡŒ Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ‚. ВмСсто этого ΠΎΠ½ Π½Π΅ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Ρ‚Ρ€ΠΈΠΆΠ΄Ρ‹ Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ копирования Widget, Π½ΠΎ Π΅Ρ‰Π΅ ΠΈ Ρ‚Ρ€ΠΈ Ρ€Π°Π·Π° скопируСт Widgetlmpl. ΠžΡ‡Π΅Π½ΡŒ нСэффСктивно!

А Π½Π°ΠΌ Π±Ρ‹ Ρ…ΠΎΡ‚Π΅Π»ΠΎΡΡŒ ΡΠΎΠΎΠ±Ρ‰ΠΈΡ‚ΡŒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ std::swap, Ρ‡Ρ‚ΠΎ ΠΏΡ€ΠΈ ΠΎΠ±ΠΌΠ΅Π½Π΅ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠ² Widget Π½ΡƒΠΆΠ½ΠΎ ΠΎΠ±ΠΌΠ΅Π½ΡΡ‚ΡŒ значСния хранящихся Π² Π½ΠΈΡ… ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»Π΅ΠΉ pimpl. И Ρ‚Π°ΠΊΠΎΠΉ способ сущСствуСт: ΡΠΏΠ΅Ρ†ΠΈΠ°Π»ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ std::swap для класса Widget. НиТС ΠΏΡ€ΠΈΠ²Π΅Π΄Π΅Π½Π° основная идСя, хотя Π² Ρ‚Π°ΠΊΠΎΠΌ Π²ΠΈΠ΄Π΅ ΠΊΠΎΠ΄ Π½Π΅ скомпилируСтся:


namespace std {

template <> // это спСциализированная вСрсия

void swap<Widget>(Widget& a, // std::swap, ΠΊΠΎΠ³Π΄Π° T Π΅ΡΡ‚ΡŒ

Widget& b) // Widget; Π½Π΅ скомпилируСтся

{

swap(a.pimpl, b.pimpl); // для ΠΎΠ±ΠΌΠ΅Π½Π° Π΄Π²ΡƒΡ… Widget просто

} // ΠΎΠ±ΠΌΠ΅Π½ΠΈΠ²Π°Π΅ΠΌ ΠΈΡ… ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΠΈ pimpl

}


Π‘Ρ‚Ρ€ΠΎΠΊΠ° Β«template <>Β» Π² Π½Π°Ρ‡Π°Π»Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π³ΠΎΠ²ΠΎΡ€ΠΈΡ‚ ΠΎ Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ это полная спСциализация шаблона std::swap, Π° Β«<Widget>Β» послС ΠΈΠΌΠ΅Π½ΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π³ΠΎΠ²ΠΎΡ€ΠΈΡ‚ ΠΎ Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ это спСциализация для случая, ΠΊΠΎΠ³Π΄Π° T Π΅ΡΡ‚ΡŒ Widget. Π”Ρ€ΡƒΠ³ΠΈΠΌΠΈ словами, ΠΊΠΎΠ³Π΄Π° ΠΎΠ±Ρ‰ΠΈΠΉ шаблон swap примСняСтся ΠΊ Widget, Ρ‚ΠΎ Π΄ΠΎΠ»ΠΆΠ½Π° Π±Ρ‹Ρ‚ΡŒ использована эта рСализация. Π’ΠΎΠΎΠ±Ρ‰Π΅-Ρ‚ΠΎ Π½Π΅ допускаСтся ΠΈΠ·ΠΌΠ΅Π½ΡΡ‚ΡŒ содСрТимоС пространства ΠΈΠΌΠ΅Π½ std, Π½ΠΎ Ρ€Π°Π·Ρ€Π΅ΡˆΠ΅Π½ΠΎ Π²Π²ΠΎΠ΄ΠΈΡ‚ΡŒ ΠΏΠΎΠ»Π½Ρ‹Π΅ спСциализации стандартных шаблонов (ΠΏΠΎΠ΄ΠΎΠ±Π½Ρ‹Ρ… swap) для созданных Π½Π°ΠΌΠΈ Ρ‚ΠΈΠΏΠΎΠ² (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, Widget). Π§Ρ‚ΠΎ ΠΌΡ‹ ΠΈ Π΄Π΅Π»Π°Π΅ΠΌ.