ប្រតិបត្តិករផ្ទុកលើសទម្ងន់។ ប្រតិបត្តិករថ្មីនិងលុប។ ទ្រនិច​ទ្រនិច​ទ្រនិច​បង្ហាញ​ប្រតិបត្តិករ

ថ្ងៃល្អ!

បំណងប្រាថ្នាចង់សរសេរអត្ថបទនេះបានលេចឡើងបន្ទាប់ពីបានអានការបង្ហោះ Overloading C++ Operators ដោយសារតែប្រធានបទសំខាន់ៗជាច្រើនមិនត្រូវបានគ្របដណ្តប់នៅក្នុងវា។

អ្វី​ដែល​សំខាន់​បំផុត​ក្នុង​ការ​ចងចាំ​នោះ​គឺ​ការ​ផ្ទុក​លើស​ចំណុះ​របស់​ប្រតិបត្តិករ​គឺ​មាន​ច្រើន​ជាង​នេះ។ វិធីងាយស្រួលមុខងារហៅទូរសព្ទ ដូច្នេះកុំយកទៅឆ្ងាយជាមួយនឹងការផ្ទុកលើសទម្ងន់របស់ប្រតិបត្តិករ។ វាគួរតែត្រូវបានប្រើតែនៅពេលដែលវានឹងធ្វើឱ្យការសរសេរកូដកាន់តែងាយស្រួល។ ប៉ុន្តែមិនច្រើនទេ ដែលធ្វើឲ្យការអានពិបាក។ យ៉ាងណាមិញ ដូចដែលអ្នកបានដឹងហើយថា កូដត្រូវបានអានញឹកញាប់ជាងវាត្រូវបានសរសេរ។ ហើយកុំភ្លេចថា អ្នកនឹងមិនត្រូវបានអនុញ្ញាតឱ្យផ្ទុកលើសទម្ងន់នៃប្រតិបត្តិករក្នុងពេលដំណាលគ្នាជាមួយនឹងប្រភេទដែលភ្ជាប់មកជាមួយនោះទេ លទ្ធភាពនៃការផ្ទុកលើសទម្ងន់គឺអាចប្រើបានសម្រាប់តែប្រភេទ/ថ្នាក់ដែលកំណត់ដោយអ្នកប្រើប្រាស់ប៉ុណ្ណោះ។

វាក្យសម្ព័ន្ធលើសទម្ងន់

វាក្យសម្ព័ន្ធសម្រាប់ការផ្ទុកលើសទម្ងន់របស់ប្រតិបត្តិករគឺស្រដៀងទៅនឹងការកំណត់មុខងារមួយហៅថា operator@ ដែល @ គឺជាអ្នកកំណត់អត្តសញ្ញាណប្រតិបត្តិករ (ឧទាហរណ៍ +, -,<<, >>) ចូរយើងពិចារណា ឧទាហរណ៍សាមញ្ញបំផុត។:
class Integer (private: int value; public: Integer(int i): value(i)() const Integer operator+(const Integer&rv) const ( return (value + rv.value); ) );
IN ក្នុងករណីនេះប្រតិបត្តិករត្រូវបានដាក់ស៊ុមជាសមាជិកនៃថ្នាក់មួយ អាគុយម៉ង់កំណត់តម្លៃដែលមានទីតាំងនៅផ្នែកខាងស្តាំនៃប្រតិបត្តិករ។ ជាទូទៅមានវិធីសំខាន់ពីរដើម្បីផ្ទុកលើសទម្ងន់ប្រតិបត្តិករ៖ មុខងារសកលរួសរាយរាក់ទាក់ចំពោះថ្នាក់ ឬមុខងារក្នុងជួរនៃថ្នាក់ខ្លួនឯង។ យើងនឹងពិចារណាថាវិធីសាស្ត្រណាដែលល្អជាងសម្រាប់ប្រតិបត្តិករណានៅចុងបញ្ចប់នៃប្រធានបទ។

ក្នុងករណីភាគច្រើន ប្រតិបត្តិករ (លើកលែងតែវត្ថុដែលមានលក្ខខណ្ឌ) ត្រឡប់វត្ថុមួយ ឬសេចក្ដីយោងទៅប្រភេទដែលអាគុយម៉ង់របស់វាជាកម្មសិទ្ធិ (ប្រសិនបើប្រភេទខុសគ្នា នោះអ្នកសម្រេចចិត្តពីរបៀបបកស្រាយលទ្ធផលនៃការវាយតម្លៃរបស់ប្រតិបត្តិករ)។

ផ្ទុកលើសទម្ងន់ប្រតិបត្តិករ unary

សូមក្រឡេកមើលឧទាហរណ៍នៃការផ្ទុកលើសចំណុះនៃប្រតិបត្តិករ unary សម្រាប់ថ្នាក់ចំនួនគត់ដែលបានកំណត់ខាងលើ។ ក្នុងពេលជាមួយគ្នានេះ ចូរយើងកំណត់ពួកវាក្នុងទម្រង់នៃមុខងារមិត្តភាព ហើយពិចារណាពីប្រតិបត្តិករបន្ថយ និងបង្កើន៖
ចំនួនគត់ថ្នាក់ (ឯកជន៖ តម្លៃ int; សាធារណៈ៖ ចំនួនគត់(int i): តម្លៃ(i) () //unary + friend const ចំនួនគត់&ប្រតិបត្តិករ+(const ចំនួនគត់&i); //unary - friend const ចំនួនគត់ប្រតិបត្តិករ-(const ចំនួនគត់&i) ;// បុព្វបទបង្កើន friend const ចំនួនគត់&ប្រតិបត្តិករ ++(ចំនួនគត់&i); //postfix increment friend const Integer operator ++(ចំនួនគត់&i, int); friend const ចំនួនគត់ប្រតិបត្តិករ--(ចំនួនគត់&i, int); ); //unary plus មិនធ្វើអ្វីទាំងអស់។ const Integer& operator+(const Integer&i) ( return i.value; ) const Integer operator-(const Integer&i) ( return Integer(-i.value); ) //prefix version ត្រឡប់តម្លៃបន្ទាប់ពី increment const Integer& operator++(Integer&i) ( i.value++; return i; ) // កំណែ postfix ត្រឡប់តម្លៃមុនពេល increment const Integer operator ++(Integer&i, int) ( Integer oldValue(i.value); i.value ++; return oldValue; ) //prefix version returns តម្លៃបន្ទាប់ពី decrement const ចំនួនគត់&ប្រតិបត្តិករ--(ចំនួនគត់&i) ( i.value--; return i; ) // កំណែ postfix ត្រឡប់តម្លៃមុនពេល decrement const Integer operator--(Integer&i, int) ( Integer oldValue(i. តម្លៃ); i .value--;
ឥឡូវអ្នកដឹងពីរបៀបដែលកម្មវិធីចងក្រងបែងចែករវាងបុព្វបទ និងកំណែ postfix នៃការបន្ថយ និងបង្កើន។ ក្នុងករណីនៅពេលដែលវាឃើញកន្សោម ++i ប្រតិបត្តិករមុខងារ ++(a) ត្រូវបានហៅ។ ប្រសិនបើវាឃើញ i++ នោះ operator ++(a, int) ត្រូវបានហៅ។ នោះគឺជាមុខងារ overloaded operator++ ត្រូវបានគេហៅថា ហើយនេះគឺជាអ្វីដែល dummy int parameter នៅក្នុងកំណែ postfix ត្រូវបានប្រើសម្រាប់។

ប្រតិបត្តិករគោលពីរ

សូមក្រឡេកមើលវាក្យសម្ព័ន្ធសម្រាប់ overloading binary operators ។ ចូរយើងផ្ទុកលើសចំនួនប្រតិបត្តិករមួយដែលត្រឡប់តម្លៃ l មួយ។ ប្រតិបត្តិករតាមលក្ខខណ្ឌហើយប្រតិបត្តិករមួយបង្កើតតម្លៃថ្មី (តោះកំណត់ពួកវាជាសកល)៖
class Integer (private: int value; public: Integer(int i): value(i) () friend const Integer operator+(const Integer&left, const Integer&right); friend Integer& operator+=(Integer&left, const Integer&right); friend bool operator==(const ចំនួនគត់&ឆ្វេង, const ចំនួនគត់&right); const Integer operator+(const Integer&left, const Integer&right) ( return Integer(left.value + right.value); ) Integer& operator+=(Integer&left, const Integer&right) (left.value += right.value; return left; ) bool operator==(const ចំនួនគត់&ឆ្វេង, const ចំនួនគត់&right) (ត្រឡប់ left.value == right.value; )
នៅក្នុងឧទាហរណ៍ទាំងអស់នេះ ប្រតិបត្តិករត្រូវបានផ្ទុកលើសទម្ងន់សម្រាប់ប្រភេទដូចគ្នា ទោះបីជាយ៉ាងណាក៏ដោយ វាមិនចាំបាច់ទេ។ ឧទាហរណ៍អ្នកអាចផ្ទុកលើសទម្ងន់ការបន្ថែមរបស់យើង។ ប្រភេទចំនួនគត់និងកំណត់តាមលក្ខណៈរបស់វា អណ្ដែត។

អាគុយម៉ង់ និងតម្លៃត្រឡប់

ដូចដែលអ្នកអាចឃើញឧទាហរណ៍ប្រើ វិធីផ្សេងៗបញ្ជូនអាគុយម៉ង់ទៅអនុគមន៍ និងតម្លៃប្រតិបត្តិករត្រឡប់។
  • ប្រសិនបើអាគុយម៉ង់មិនត្រូវបានកែប្រែដោយប្រតិបត្តិករទេ ក្នុងករណីឧទាហរណ៍ unary plus វាត្រូវតែឆ្លងកាត់ជាឯកសារយោងទៅថេរមួយ។ ជាទូទៅនេះជាការពិតសម្រាប់ស្ទើរតែគ្រប់គ្នា ប្រតិបត្តិករនព្វន្ធ(បូក ដក គុណ...)
  • ប្រភេទនៃតម្លៃត្រឡប់មកវិញអាស្រ័យលើលក្ខណៈរបស់ប្រតិបត្តិករ។ ប្រសិនបើប្រតិបត្តិករត្រូវតែត្រឡប់តម្លៃថ្មី នោះចាំបាច់ត្រូវបង្កើត វត្ថុថ្មី។(ដូចនៅក្នុងករណីនៃ binary បូក) ។ ប្រសិនបើ​អ្នក​ចង់​ការពារ​វត្ថុ​ពី​ការ​កែប្រែ​ជា l-value នោះ​អ្នក​ត្រូវ​ត្រឡប់​វា​ជា​ថេរ។
  • ប្រតិបត្តិករកិច្ចការត្រូវតែត្រឡប់សេចក្តីយោងទៅធាតុដែលបានផ្លាស់ប្តូរ។ ផងដែរ ប្រសិនបើអ្នកចង់ប្រើ assignment operator ក្នុង constructs ដូចជា (x=y).f() ដែលអនុគមន៍ f() ត្រូវបានហៅសម្រាប់ variable x បន្ទាប់ពីកំណត់វាទៅ y បន្ទាប់មកកុំត្រឡប់សេចក្តីយោងទៅ ថេរ គ្រាន់តែត្រឡប់ឯកសារយោង។
  • ប្រតិបត្តិករឡូជីខលគួរតែត្រឡប់ int នៅអាក្រក់បំផុត និង bool ល្អបំផុត។

ត្រឡប់តម្លៃបង្កើនប្រសិទ្ធភាព

នៅពេលបង្កើតវត្ថុថ្មី និងបញ្ជូនពួកវាមកវិញពីមុខងារមួយ អ្នកគួរតែប្រើសញ្ញាណដែលស្រដៀងនឹងឧទាហរណ៍នៃ binary plus operator ដែលបានពិពណ៌នាខាងលើ។
ត្រឡប់ចំនួនគត់(left.value + right.value);
និយាយឱ្យត្រង់ទៅ ខ្ញុំមិនដឹងថាស្ថានភាពបែបណាដែលពាក់ព័ន្ធសម្រាប់ C ++ 11;
នៅ glance ដំបូង វាមើលទៅស្រដៀងនឹងវាក្យសម្ព័ន្ធសម្រាប់បង្កើតវត្ថុបណ្តោះអាសន្ន ពោលគឺវាហាក់ដូចជាមិនមានភាពខុសគ្នារវាងកូដខាងលើ និងនេះទេ៖
ចំនួនគត់ temp(left.value + right.value); សីតុណ្ហភាពត្រឡប់មកវិញ;
ប៉ុន្តែតាមពិតក្នុងករណីនេះ អ្នកសាងសង់នឹងត្រូវបានហៅក្នុងជួរទីមួយ បន្ទាប់មកអ្នកបង្កើតច្បាប់ចម្លងនឹងត្រូវបានហៅ ដែលនឹងចម្លងវត្ថុ ហើយបន្ទាប់មកនៅពេលដែល unwinding ជង់ អ្នកបំផ្លាញនឹងត្រូវបានហៅ។ នៅពេលប្រើធាតុទីមួយ កម្មវិធីចងក្រងដំបូងបង្កើតវត្ថុនៅក្នុងអង្គចងចាំដែលវាត្រូវការចម្លង ដូច្នេះរក្សាទុកការហៅទៅអ្នកបង្កើតច្បាប់ចម្លង និងអ្នកបំផ្លាញ។

ប្រតិបត្តិករពិសេស

C ++ មានប្រតិបត្តិករដែលមានវាក្យសម្ព័ន្ធជាក់លាក់ និងវិធីសាស្ត្រផ្ទុកលើសទម្ងន់។ ឧទាហរណ៍ ប្រតិបត្តិករធ្វើលិបិក្រម។ វាតែងតែត្រូវបានកំណត់ថាជាសមាជិកនៃថ្នាក់មួយ ហើយចាប់តាំងពីវត្ថុដែលបានធ្វើលិបិក្រមមានបំណងធ្វើដូចអារេ វាគួរតែត្រឡប់សេចក្តីយោងមួយ។
សញ្ញាក្បៀស
ប្រតិបត្តិករ "ពិសេស" ក៏រួមបញ្ចូលសញ្ញាក្បៀសផងដែរ។ វា​ត្រូវ​បាន​ហៅ​លើ​វត្ថុ​ដែល​មាន​សញ្ញាក្បៀស​នៅ​ជាប់​នឹង​វា (ប៉ុន្តែ​វា​មិន​ត្រូវ​បាន​ហៅ​ក្នុង​បញ្ជី​អាគុយម៉ង់​មុខងារ)។ ការមកជាមួយករណីប្រើប្រាស់ដ៏មានអត្ថន័យសម្រាប់ប្រតិបត្តិករនេះមិនងាយស្រួលនោះទេ។ Habrowser AxisPod នៅក្នុងសេចក្តីអធិប្បាយទៅកាន់អត្ថបទមុនអំពីការផ្ទុកលើសទម្ងន់បាននិយាយអំពីរឿងមួយ។
ទ្រនិច​ទ្រនិច​ទ្រនិច​បង្ហាញ​ប្រតិបត្តិករ
ការផ្ទុកលើសទម្ងន់នៃប្រតិបត្តិករទាំងនេះអាចត្រូវបានរាប់ជាសុចរិតសម្រាប់ថ្នាក់ទ្រនិចឆ្លាតវៃ។ ប្រតិបត្តិករនេះត្រូវបានកំណត់ជាចាំបាច់ជាមុខងារថ្នាក់ ហើយការរឹតបន្តឹងមួយចំនួនត្រូវបានដាក់លើវា៖ វាត្រូវតែត្រឡប់វត្ថុ (ឬឯកសារយោង) ឬទ្រនិចដែលអនុញ្ញាតឱ្យចូលប្រើវត្ថុ។
ប្រតិបត្តិករចាត់តាំង
ប្រតិបត្តិករកិច្ចការត្រូវបានកំណត់ជាចាំបាច់ជាមុខងារថ្នាក់ ពីព្រោះវាត្រូវបានភ្ជាប់ខាងក្នុងទៅវត្ថុនៅខាងឆ្វេងនៃ "=" ។ ការកំណត់ប្រតិបត្តិករកិច្ចការក្នុង ជាសកលនឹងធ្វើឱ្យវាអាចបដិសេធឥរិយាបថលំនាំដើមរបស់ប្រតិបត្តិករ "=" ។ ឧទាហរណ៍៖
class Integer (private: int value; public: Integer(int i): value(i) () Integer& operator=(const Integer&right) ( //check for self-assignment if (this == &right) ( return * this; ) តម្លៃ = right.value;

ដូចដែលអ្នកបានឃើញហើយ នៅដើមដំបូងនៃមុខងារ ការត្រួតពិនិត្យត្រូវបានបង្កើតឡើងសម្រាប់ការចាត់តាំងដោយខ្លួនឯង។ ជាទូទៅ ក្នុងករណីនេះ ការសម្រេចដោយខ្លួនឯងគឺមិនបង្កគ្រោះថ្នាក់ទេ ប៉ុន្តែស្ថានភាពមិនតែងតែសាមញ្ញនោះទេ។ ឧទាហរណ៍ ប្រសិនបើវត្ថុមានទំហំធំ អ្នកអាចចំណាយពេលច្រើនលើវា។ ការចម្លងមិនចាំបាច់ឬនៅពេលធ្វើការជាមួយទ្រនិច។

ប្រតិបត្តិករដែលមិនអាចផ្ទុកលើសទម្ងន់បាន។
ប្រតិបត្តិករមួយចំនួននៅក្នុង C ++ មិនផ្ទុកលើសទម្ងន់ទាល់តែសោះ។ ជាក់ស្តែង នេះត្រូវបានធ្វើសម្រាប់ហេតុផលសុវត្ថិភាព។
  • ប្រតិបត្តិករជ្រើសរើសសមាជិកថ្នាក់ ".".
  • ប្រតិបត្តិករសម្រាប់ការបង្វែរទ្រនិចទៅសមាជិកថ្នាក់ ".*"
  • C ++ មិនមានប្រតិបត្តិករនិទស្សន្ត (ដូចនៅក្នុង Fortran) "**" ទេ។
  • វាត្រូវបានហាមឃាត់មិនឱ្យកំណត់ប្រតិបត្តិករផ្ទាល់ខ្លួនរបស់អ្នក (អាចមានបញ្ហាក្នុងការកំណត់អាទិភាព)។
  • អាទិភាពប្រតិបត្តិករមិនអាចផ្លាស់ប្តូរបានទេ។
ដូចដែលយើងបានរកឃើញរួចហើយ មានវិធីពីរយ៉ាងនៃប្រតិបត្តិករ - ជាមុខងារថ្នាក់ និងជាមុខងារសកលដែលមានលក្ខណៈមិត្តភាព។
Rob Murray នៅក្នុងសៀវភៅ C++ Strategies and Tactics របស់គាត់បានកំណត់ អនុសាសន៍ខាងក្រោមតាមជម្រើសនៃទម្រង់ប្រតិបត្តិករ៖

ហេតុ​អ្វី​បាន​ជា​យ៉ាង​នេះ? ទីមួយ ប្រតិបត្តិករមួយចំនួនមានកម្រិតដំបូង។ ជាទូទៅ ប្រសិនបើមិនមានភាពខុសគ្នាតាមន័យធៀបនៅក្នុងរបៀបដែលប្រតិបត្តិករត្រូវបានកំណត់ទេនោះ វាជាការប្រសើរក្នុងការរចនាវាជាមុខងារថ្នាក់ ដើម្បីបញ្ជាក់ពីការតភ្ជាប់ ហើយលើសពីនេះទៀតមុខងារនឹងស្ថិតនៅក្នុងជួរ។ បន្ថែមពីលើនេះ ជួនកាលវាអាចមានតម្រូវការតំណាងឱ្យ operand ខាងឆ្វេងជាវត្ថុនៃថ្នាក់ផ្សេងទៀត។ ប្រហែលជាច្រើនបំផុត ឧទាហរណ៍ភ្លឺ- បដិសេធ<< и >> សម្រាប់ស្ទ្រីម I/O ។

អក្សរសាស្ត្រ

Bruce Eckel - ទស្សនវិជ្ជា C ++ ។ ការណែនាំអំពីស្តង់ដារ C ++ ។

ស្លាក: បន្ថែមស្លាក

យើងបានគ្របដណ្តប់មូលដ្ឋាននៃការប្រើប្រាស់ការផ្ទុកលើសទម្ងន់របស់ប្រតិបត្តិករ។ នៅក្នុងសម្ភារៈនេះ ប្រតិបត្តិករ C ++ ដែលផ្ទុកលើសទម្ងន់នឹងត្រូវបានបង្ហាញដល់ការយកចិត្តទុកដាក់របស់អ្នក។ ផ្នែកនីមួយៗត្រូវបានកំណត់លក្ខណៈដោយន័យវិទ្យា, i.e. អាកប្បកិរិយារំពឹងទុក។ លើសពីនេះទៀត វិធីធម្មតាដើម្បីប្រកាស និងអនុវត្តប្រតិបត្តិករនឹងត្រូវបានបង្ហាញ។

នៅក្នុងឧទាហរណ៍កូដ X បង្ហាញពីប្រភេទកំណត់ដោយអ្នកប្រើប្រាស់ ដែលប្រតិបត្តិករត្រូវបានអនុវត្ត។ T គឺជាប្រភេទស្រេចចិត្ត ដែលកំណត់ដោយអ្នកប្រើប្រាស់ ឬភ្ជាប់មកជាមួយ។ ប៉ារ៉ាម៉ែត្រនៃប្រតិបត្តិករគោលពីរនឹងត្រូវបានដាក់ឈ្មោះថា lhs និង rhs ។ ប្រសិនបើ​ប្រតិបត្តិករ​ត្រូវ​បាន​ប្រកាស​ជា​វិធីសាស្ត្រ​ថ្នាក់ នោះ​ការ​ប្រកាស​របស់​វា​នឹង​ត្រូវ​បាន​ដាក់​បុព្វបទ​ដោយ X:: .

ប្រតិបត្តិករ =

  • និយមន័យពីស្តាំទៅឆ្វេង៖ មិនដូចប្រតិបត្តិករភាគច្រើនទេ operator= is right associative, i.e. a = b = c មានន័យថា a = (b = c) ។

ចម្លង

  • សមីការ៖ កិច្ចការ a = b ។ តម្លៃ ឬស្ថានភាពនៃ b ត្រូវបានបញ្ជូនទៅ a . លើសពីនេះ ឯកសារយោងទៅ a ត្រូវបានបញ្ជូនមកវិញ។ នេះអនុញ្ញាតឱ្យអ្នកបង្កើតខ្សែសង្វាក់ដូចជា c = a = b ។
  • ការផ្សាយពាណិជ្ជកម្មធម្មតា។: X&X::operator= (X const& rhs) ។ ប្រភេទផ្សេងទៀតនៃអាគុយម៉ង់គឺអាចធ្វើទៅបាន ប៉ុន្តែទាំងនេះមិនត្រូវបានប្រើញឹកញាប់ទេ។
  • ការអនុវត្តធម្មតា។: X&X::operator= (X const& rhs) (ប្រសិនបើ (នេះ != &rhs) ( // អនុវត្តការចម្លងធាតុប្រកបដោយប្រាជ្ញា ឬ៖ X tmp(rhs); // ចម្លង constructor swap(tmp); ) ត្រឡប់ * នេះ; )

ផ្លាស់ទី (ចាប់តាំងពី C++11)

  • សមីការ៖ កិច្ចការ a = បណ្តោះអាសន្ន() ។ តម្លៃ ឬស្ថានភាពនៃតម្លៃត្រឹមត្រូវត្រូវបានកំណត់ទៅ a ដោយផ្លាស់ទីមាតិកា។ ឯកសារយោងទៅ a ត្រូវបានបញ្ជូនមកវិញ។
  • : X&X::operator= (X&& rhs) ( // យកចិត្តពី rhs ត្រឡប់ * នេះ ; )
  • បានបង្កើតកម្មវិធីចងក្រង operator= : compiler អាចបង្កើតបានតែពីរប្រភេទនៃ operator នេះប៉ុណ្ណោះ។ ប្រសិនបើប្រតិបត្តិករមិនត្រូវបានប្រកាសនៅក្នុងថ្នាក់ទេ អ្នកចងក្រងព្យាយាមបង្កើតច្បាប់ចម្លងសាធារណៈ និងផ្លាស់ទីប្រតិបត្តិករ។ ចាប់តាំងពី C ++ 11 កម្មវិធីចងក្រងអាចបង្កើត default operator: X&X::operator= (X const& rhs) = default;

    សេចក្តីថ្លែងការណ៍ដែលបានបង្កើតគឺគ្រាន់តែចម្លង / ផ្លាស់ទី ធាតុដែលបានបញ្ជាក់ប្រសិនបើប្រតិបត្តិការបែបនេះត្រូវបានអនុញ្ញាត។

ប្រតិបត្តិករ +, -, *, /, %

  • សមីការ: ប្រតិបត្តិការបូក ដក គុណ ចែក ចែកជាមួយសល់។ វត្ថុថ្មីមួយដែលមានតម្លៃលទ្ធផលត្រូវបានត្រឡប់។
  • សេចក្តីប្រកាស និងការអនុវត្តធម្មតា។: X operator+ (X const lhs, X const rhs) ( X tmp(lhs); tmp += rhs; return tmp; )

    ជាធម្មតា ប្រសិនបើ operator+ មាន នោះវាសមហេតុផលផងដែរក្នុងការផ្ទុកលើសទម្ងន់ operator+= ដើម្បីប្រើសញ្ញា a += b ជំនួសឱ្យ a = a + b ។ ប្រសិនបើប្រតិបត្តិករ += មិនត្រូវបានផ្ទុកលើសទម្ងន់ទេ ការអនុវត្តនឹងមើលទៅដូចនេះ៖

    ប្រតិបត្តិករ X+ (X const&lhs, X const& rhs) ( // បង្កើតវត្ថុថ្មីដែលតំណាងឱ្យផលបូកនៃ lhs និង rhs: ត្រឡប់ lhs.plus(rhs); )

ប្រតិបត្តិករ Unary +, —

  • សមីការ៖ សញ្ញាវិជ្ជមាន ឬអវិជ្ជមាន។ ប្រតិបត្តិករ + ជាធម្មតាមិនធ្វើអ្វីទេ ដូច្នេះហើយ ពិបាកប្រើណាស់។ ប្រតិបត្តិករ- ត្រឡប់អាគុយម៉ង់ដែលមានសញ្ញាផ្ទុយ។
  • សេចក្តីប្រកាស និងការអនុវត្តធម្មតា។: X X::operator- () const (ត្រឡប់ /* ច្បាប់ចម្លងអវិជ្ជមាននៃ * នេះ */; ) X X::operator+ () const (ត្រឡប់ * នេះ; )

ប្រតិបត្តិករ<<, >>

  • សមីការ៖ នៅក្នុងប្រភេទដែលភ្ជាប់មកជាមួយ ប្រតិបត្តិករត្រូវបានប្រើដើម្បីផ្លាស់ប្តូរអាគុយម៉ង់ខាងឆ្វេង។ ការផ្ទុកលើសចំណុះនៃប្រតិបត្តិករទាំងនេះជាមួយនឹងន័យន័យនេះគឺកម្រមានតែមួយគត់ដែលគិតដល់គឺ std::bitset ។ ទោះជាយ៉ាងណាក៏ដោយ អត្ថន័យថ្មីត្រូវបានណែនាំសម្រាប់ធ្វើការជាមួយស្ទ្រីម ហើយការផ្ទុកលើសទម្ងន់របស់ប្រតិបត្តិករ I/O គឺជារឿងធម្មតាណាស់។
  • សេចក្តីប្រកាស និងការអនុវត្តធម្មតា។៖ ដោយសារអ្នកមិនអាចបន្ថែមវិធីសាស្រ្តទៅថ្នាក់ iostream ស្តង់ដារ ការផ្លាស់ប្តូរ operators សម្រាប់ classs ដែលអ្នកកំណត់ត្រូវតែផ្ទុកលើសទម្ងន់ជាមុខងារឥតគិតថ្លៃ៖ ostream & operator<< (ostream& os, X const& x) { os << /* the formatted data of rhs you want to print */; return os; } istream& operator>> (istream&is, X&x) ( SomeData sd; SomeMoreData smd; ប្រសិនបើ (គឺ >> sd >> smd) ( rhs.setSomeData(sd); rhs.setSomeMoreData(smd); ) ត្រឡប់ lhs; )

    លើសពីនេះទៀត ប្រភេទនៃ operand ខាងឆ្វេងអាចជា class ណាមួយដែលគួរមានឥរិយាបទដូចជា I/O object ពោលគឺ operand ខាងស្ដាំអាចជាប្រភេទ built-in ។

    MyIO & MyIO:: ប្រតិបត្តិករ<< (int rhs) { doYourThingWith(rhs); return *this; }

ប្រតិបត្តិករគោលពីរ&, |, ^

  • សមីការ៖ ប្រតិបត្តិការប៊ីត “និង”, “ឬ”, “ផ្តាច់មុខ ឬ”។ ប្រតិបត្តិករទាំងនេះផ្ទុកលើសទម្ងន់កម្រណាស់។ ជាថ្មីម្តងទៀតឧទាហរណ៍តែមួយគត់គឺ std::bitset ។

ប្រតិបត្តិករ +=, -=, *=, /=, %=

  • សមីការ៖ a += b ជាធម្មតាមានន័យដូចគ្នានឹង a = a + b ។ អាកប្បកិរិយារបស់ប្រតិបត្តិករផ្សេងទៀតគឺស្រដៀងគ្នា។
  • និយមន័យនិងការអនុវត្តធម្មតា។៖ ចាប់តាំងពីប្រតិបត្តិការកែប្រែ operand ខាងឆ្វេង ការបញ្ជូនប្រភេទលាក់គឺមិនចង់បានទេ។ ដូច្នេះ ប្រតិបត្តិករទាំងនេះត្រូវតែផ្ទុកលើសទម្ងន់ជាវិធីសាស្ត្រថ្នាក់។ X&X::operator+= (X const& rhs) ( // អនុវត្តការផ្លាស់ប្តូរទៅ * this return * this; )

ប្រតិបត្តិករ&=, |=, ^=,<<=, >>=

  • សមីការ៖ ស្រដៀងទៅនឹងប្រតិបត្តិករ += ប៉ុន្តែសម្រាប់ប្រតិបត្តិការឡូជីខល។ ប្រតិបត្តិករទាំងនេះផ្ទុកលើសទម្ងន់កម្រដូចប្រតិបត្តិករ| ល។ ប្រតិបត្តិករ<<= и operator>>= មិនត្រូវបានប្រើសម្រាប់ប្រតិបត្តិការ I/O ដោយសារតែប្រតិបត្តិករ<< и operator>> ផ្លាស់ប្តូរអាគុយម៉ង់ខាងឆ្វេងរួចហើយ។

ប្រតិបត្តិករ ==, !=

  • សមីការ៖ តេស្តសម្រាប់សមភាព/វិសមភាព។ អត្ថន័យនៃសមភាពប្រែប្រួលយ៉ាងខ្លាំងទៅតាមថ្នាក់។ ក្នុងករណីណាក៏ដោយ ពិចារណាលើលក្ខណៈសម្បត្តិនៃសមភាពដូចខាងក្រោមៈ
    1. ការឆ្លុះបញ្ចាំង, i.e. ក == ក។
    2. ស៊ីមេទ្រី, i.e. ប្រសិនបើ a == b បន្ទាប់មក b == a ។
    3. អន្តរកាល, i.e. ប្រសិនបើ a == b និង b == c នោះ a == c ។
  • សេចក្តីប្រកាស និងការអនុវត្តធម្មតា។: bool operator== (X const&lhs, X cosnt&rhs) ( return /* check for whatever means equality */ ) bool operator!= (X const&lhs, X const&rhs) ( return !(lhs == rhs); )

    ការអនុវត្តទីពីរនៃប្រតិបត្តិករ!= ជៀសវាងការធ្វើកូដដដែលៗ និងលុបបំបាត់ភាពមិនច្បាស់លាស់ដែលអាចកើតមានទាក់ទងនឹងវត្ថុទាំងពីរណាមួយ។

ប្រតិបត្តិករ<, <=, >, >=

  • សមីការ៖ ពិនិត្យ​មើល​សមាមាត្រ (ច្រើន តិច ។ល។)។ ជាធម្មតាត្រូវបានគេប្រើប្រសិនបើលំដាប់នៃធាតុត្រូវបានកំណត់តែមួយគត់ នោះគឺជា វត្ថុស្មុគស្មាញវាគ្មានន័យទេក្នុងការប្រៀបធៀបជាមួយនឹងលក្ខណៈមួយចំនួន។
  • សេចក្តីប្រកាស និងការអនុវត្តធម្មតា។៖ bool operator< (X const& lhs, X const& rhs) { return /* compare whatever defines the order */ } bool operator>(X const&lhs, X const&rhs) (ត្រឡប់ rhs< lhs; }

    ការអនុវត្តប្រតិបត្តិករ> ដោយប្រើប្រតិបត្តិករ< или наоборот обеспечивает однозначное определение. operator<= может быть реализован по-разному, в зависимости от ситуации . В частности, при отношении строго порядка operator== можно реализовать лишь через operator< :

    Bool operator== (X const&lhs, X const&rhs) ( return !(lhs< rhs) && !(rhs < lhs); }

ប្រតិបត្តិករ ++, -

  • សមីការ៖ a++ (ក្រោយការបង្កើន) បង្កើនតម្លៃដោយ 1 ហើយត្រឡប់ ចាស់អត្ថន័យ។ ++a (បង្កើនមុន) ត្រឡប់មកវិញ ថ្មី។អត្ថន័យ។ ជាមួយនឹងប្រតិបត្តិករបន្ថយ - អ្វីគ្រប់យ៉ាងគឺស្រដៀងគ្នា។
  • សេចក្តីប្រកាស និងការអនុវត្តធម្មតា។: X&X::operator++() ( //preincrement /* somehow increment ឧ. *this += 1*/; return * this; ) X X::operator++(int) ( //postincrement X oldValue(* this); + +(* នេះ);

ប្រតិបត្តិករ ()

  • សមីការ៖ ការប្រតិបត្តិវត្ថុអនុគមន៍ (functor) ។ ជាធម្មតាប្រើមិនមែនដើម្បីកែប្រែវត្ថុនោះទេ ប៉ុន្តែប្រើវាជាមុខងារ។
  • មិនមានការរឹតបន្តឹងលើប៉ារ៉ាម៉ែត្រទេ។៖ មិនដូចប្រតិបត្តិករមុនទេ ក្នុងករណីនេះមិនមានការរឹតបន្តឹងលើចំនួន និងប្រភេទនៃប៉ារ៉ាម៉ែត្រទេ។ ប្រតិបត្តិករអាចត្រូវបានផ្ទុកលើសទម្ងន់ជាវិធីសាស្ត្រថ្នាក់ប៉ុណ្ណោះ។
  • ឧទាហរណ៍ការផ្សាយពាណិជ្ជកម្ម: Foo X::operator() (Bar br, Baz const&bz);

ប្រតិបត្តិករ

  • សមីការ៖ ចូលប្រើធាតុនៃអារេ ឬកុងតឺន័រ ឧទាហរណ៍ក្នុង std::vector , std::map , std::array ។
  • សេចក្តីប្រកាស៖ ប្រភេទប៉ារ៉ាម៉ែត្រអាចជាអ្វីក៏បាន។ ប្រភេទ​ត្រឡប់​ជា​ធម្មតា​ជា​ការ​យោង​ទៅ​នឹង​អ្វី​ដែល​ត្រូវ​បាន​រក្សា​ទុក​ក្នុង​កុងតឺន័រ។ ជាញឹកញាប់ប្រតិបត្តិករត្រូវបានផ្ទុកលើសទម្ងន់ជាពីរកំណែ const និង non-const: Element_t&X::operator(Index_t const&index); const Element_t&X::operator(Index_t const&index) const;

ប្រតិបត្តិករ!

  • សមីការ៖ ការបដិសេធក្នុងន័យឡូជីខល។
  • សេចក្តីប្រកាស និងការអនុវត្តធម្មតា។: bool X::operator!() const ( return !/* some evaluation of *this*/; )

bool ប្រតិបត្តិករច្បាស់លាស់

  • សមីការ៖ ប្រើក្នុងបរិបទឡូជីខល។ ភាគច្រើនប្រើជាមួយទ្រនិចឆ្លាតវៃ។
  • ការអនុវត្ត: explicit X::operator bool() const ( return /* if this true or false */; )

ប្រតិបត្តិករ &&, ||

  • សមីការ៖ ឡូជីខល "និង", "ឬ" ។ ប្រតិបត្តិករទាំងនេះត្រូវបានកំណត់សម្រាប់តែប្រភេទប៊ូលីនដែលភ្ជាប់មកជាមួយ ហើយដំណើរការលើមូលដ្ឋានខ្ជិល ពោលគឺអាគុយម៉ង់ទីពីរត្រូវបានពិចារណាលុះត្រាតែទីមួយមិនកំណត់លទ្ធផល។ នៅពេលផ្ទុកលើសទម្ងន់ ទ្រព្យសម្បត្តិនេះត្រូវបានបាត់បង់ ដូច្នេះប្រតិបត្តិករទាំងនេះកម្រនឹងផ្ទុកលើសទម្ងន់ណាស់។

ប្រតិបត្តិករ Unary *

  • សមីការ៖ សេចក្តីយោងទ្រនិច។ ជាធម្មតាផ្ទុកលើសទម្ងន់សម្រាប់ថ្នាក់ដែលមានឧបករណ៍ចង្អុលឆ្លាតវៃ និងឧបករណ៍សរសេរឡើងវិញ។ ត្រឡប់​សេចក្ដី​យោង​ទៅ​កាន់​កន្លែង​ដែល​វត្ថុ​ចង្អុល ។
  • សេចក្តីប្រកាស និងការអនុវត្តធម្មតា។: T&X::operator*() const ( return *_ptr; )

ប្រតិបត្តិករ->

  • សមីការ៖ ចូល​ប្រើ​វាល​ដោយ​ទ្រនិច។ ដូច​ឧបករណ៍​មុន​ដែរ ប្រតិបត្តិករ​នេះ​ផ្ទុក​លើស​ទម្ងន់​សម្រាប់​ប្រើ​ជាមួយ​ឧបករណ៍​ចង្អុល​ឆ្លាតវៃ និង​ឧបករណ៍​បំប្លែង។ ប្រសិនបើប្រតិបត្តិករ -> ត្រូវបានជួបប្រទះនៅក្នុងលេខកូដរបស់អ្នក អ្នកចងក្រងបញ្ជូនបន្តការហៅទៅកាន់ប្រតិបត្តិករ -> ប្រសិនបើលទ្ធផលនៃប្រភេទផ្ទាល់ខ្លួនត្រូវបានបញ្ជូនត្រឡប់មកវិញ។
  • ការអនុវត្តធម្មតា។: T* X::operator->() const ( return _ptr; )

ប្រតិបត្តិករ->*

  • សមីការ៖ ចូលប្រើទ្រនិចទៅវាលដោយទ្រនិច។ ប្រតិបត្តិករយកទ្រនិចទៅវាលមួយ ហើយអនុវត្តវាទៅអ្វីក៏ដោយ * ចំណុចនេះទៅ ដូច្នេះ objPtr->*memPtr គឺដូចគ្នានឹង (*objPtr)*memPtr ។ កម្រប្រើណាស់។
  • ការអនុវត្តដែលអាចធ្វើបាន៖ គំរូ T&X::operator->*(T V::* memptr) (return (operator*())).*memptr;)

    នៅទីនេះ X គឺជាទ្រនិចដ៏ឆ្លាតវៃ V គឺជាប្រភេទចង្អុលទៅដោយ X ហើយ T គឺជាប្រភេទចង្អុលទៅដោយទ្រនិចវាល។ មិនគួរឱ្យភ្ញាក់ផ្អើលទេដែលប្រតិបត្តិករនេះកម្រនឹងផ្ទុកលើសទម្ងន់។

ប្រតិបត្តិករ Unary&

  • សមីការ៖ ប្រតិបត្តិករអាសយដ្ឋាន។ ប្រតិបត្តិករនេះផ្ទុកលើសទម្ងន់កម្រណាស់។

ប្រតិបត្តិករ

  • សមីការ៖ សញ្ញាក្បៀសដែលភ្ជាប់មកជាមួយបានអនុវត្តចំពោះកន្សោមពីរវាយតម្លៃពួកវាទាំងក្នុងលំដាប់ជាលាយលក្ខណ៍អក្សរ និងត្រឡប់តម្លៃនៃសញ្ញាទីពីរ។ វាមិនត្រូវបានណែនាំឱ្យផ្ទុកលើសទម្ងន់ទេ។

ប្រតិបត្តិករ ~

  • សមីការ៖ ប្រតិបត្តិករបញ្ច្រាសបន្តិច។ មួយនៃប្រតិបត្តិករកម្រប្រើបំផុត។

ប្រតិបត្តិករខាស

  • សមីការ៖ អនុញ្ញាត​ឱ្យ​ដាក់​វត្ថុ​ថ្នាក់​ដោយ​មិន​ច្បាស់លាស់ ឬ​ច្បាស់លាស់​ទៅ​ប្រភេទ​ផ្សេង​ទៀត។
  • សេចក្តីប្រកាស: // ការបំប្លែងទៅជា T, ច្បាស់លាស់ ឬបង្កប់ន័យ X::operator T() const; // ការបំប្លែងជាក់លាក់ទៅជា U const& explicit X::operator U const&() const; // ការបំប្លែងទៅជា V&V&X::operator V&();

    ការ​ប្រកាស​ទាំង​នេះ​មើល​ទៅ​ចម្លែក​ព្រោះ​ពួកគេ​ខ្វះ​ប្រភេទ​ត្រឡប់។ វាគឺជាផ្នែកមួយនៃឈ្មោះប្រតិបត្តិករ ហើយមិនត្រូវបានបញ្ជាក់ពីរដងទេ។ វាមានតម្លៃចងចាំវា។ ចំនួនធំខ្មោចដែលលាក់កំបាំងអាចចូល កំហុសដែលមិនបានរំពឹងទុកនៅក្នុងប្រតិបត្តិការនៃកម្មវិធី។

ប្រតិបត្តិករថ្មី ថ្មី លុប លុប

ប្រតិបត្តិករទាំងនេះគឺខុសគ្នាទាំងស្រុងពីឧបករណ៍ខាងលើទាំងអស់ព្រោះវាមិនដំណើរការជាមួយ ប្រភេទផ្ទាល់ខ្លួន. ការផ្ទុកលើសទម្ងន់របស់ពួកគេគឺស្មុគស្មាញណាស់ហើយដូច្នេះវានឹងមិនត្រូវបានគេពិចារណានៅទីនេះទេ។

សេចក្តីសន្និដ្ឋាន

គំនិតសំខាន់គឺនេះ៖ កុំផ្ទុកប្រតិបត្តិករលើសទម្ងន់ព្រោះអ្នកដឹងពីរបៀបធ្វើវា។ ផ្ទុកលើសទម្ងន់តែក្នុងករណីដែលវាហាក់ដូចជាធម្មជាតិ និងចាំបាច់ប៉ុណ្ណោះ។ ប៉ុន្តែត្រូវចាំថា ប្រសិនបើអ្នកផ្ទុកលើសទម្ងន់ប្រតិបត្តិករមួយ អ្នកនឹងត្រូវផ្ទុកលើសទម្ងន់ផ្សេងទៀត។

ថ្ងៃល្អ!

បំណងប្រាថ្នាចង់សរសេរអត្ថបទនេះបានលេចឡើងបន្ទាប់ពីអានការបង្ហោះព្រោះប្រធានបទសំខាន់ៗជាច្រើនមិនត្រូវបានគ្របដណ្តប់នៅក្នុងវា។

អ្វី​ដែល​សំខាន់​បំផុត​ក្នុង​ការ​ចងចាំ​នោះ​គឺ​ការ​ផ្ទុក​លើស​ចំណុះ​របស់​ប្រតិបត្តិករ​គឺ​គ្រាន់​តែ​ជា​មធ្យោបាយ​ងាយស្រួល​ជាង​ក្នុង​ការ​ហៅ​ទៅ​មុខងារ ដូច្នេះ​ហើយ​កុំ​ឲ្យ​វា​ទៅ​ឆ្ងាយ​ជាមួយ​ការ​ផ្ទុក​លើស​ចំណុះ។ វាគួរតែត្រូវបានប្រើតែនៅពេលដែលវានឹងធ្វើឱ្យការសរសេរកូដកាន់តែងាយស្រួល។ ប៉ុន្តែមិនច្រើនទេ ដែលធ្វើឲ្យការអានពិបាក។ យ៉ាងណាមិញ ដូចដែលអ្នកបានដឹងហើយថា កូដត្រូវបានអានញឹកញាប់ជាងវាត្រូវបានសរសេរ។ ហើយកុំភ្លេចថា អ្នកនឹងមិនត្រូវបានអនុញ្ញាតឱ្យផ្ទុកលើសទម្ងន់នៃប្រតិបត្តិករក្នុងពេលដំណាលគ្នាជាមួយនឹងប្រភេទដែលភ្ជាប់មកជាមួយនោះទេ លទ្ធភាពនៃការផ្ទុកលើសទម្ងន់គឺអាចប្រើបានសម្រាប់តែប្រភេទ/ថ្នាក់ដែលកំណត់ដោយអ្នកប្រើប្រាស់ប៉ុណ្ណោះ។

វាក្យសម្ព័ន្ធលើសទម្ងន់

វាក្យសម្ព័ន្ធសម្រាប់ការផ្ទុកលើសទម្ងន់របស់ប្រតិបត្តិករគឺស្រដៀងទៅនឹងការកំណត់មុខងារមួយហៅថា operator@ ដែល @ គឺជាអ្នកកំណត់អត្តសញ្ញាណប្រតិបត្តិករ (ឧទាហរណ៍ +, -,<<, >>) តោះមើលឧទាហរណ៍សាមញ្ញមួយ៖
class Integer (private: int value; public: Integer(int i): value(i)() const Integer operator+(const Integer&rv) const ( return (value + rv.value); ) );
ក្នុងករណីនេះ ប្រតិបត្តិករត្រូវបានដាក់ស៊ុមជាសមាជិកនៃថ្នាក់មួយ អាគុយម៉ង់កំណត់តម្លៃដែលមានទីតាំងនៅផ្នែកខាងស្តាំនៃប្រតិបត្តិករ។ ជាទូទៅ មានវិធីសំខាន់ពីរក្នុងការផ្ទុកលើសទម្ងន់របស់ប្រតិបត្តិករ៖ មុខងារសកលដែលមានលក្ខណៈរួសរាយរាក់ទាក់ចំពោះថ្នាក់ ឬមុខងារក្នុងជួរនៃថ្នាក់ខ្លួនឯង។ យើងនឹងពិចារណាថាវិធីសាស្ត្រណាដែលល្អជាងសម្រាប់ប្រតិបត្តិករណានៅចុងបញ្ចប់នៃប្រធានបទ។

ក្នុងករណីភាគច្រើន ប្រតិបត្តិករ (លើកលែងតែវត្ថុដែលមានលក្ខខណ្ឌ) ត្រឡប់វត្ថុមួយ ឬសេចក្ដីយោងទៅប្រភេទដែលអាគុយម៉ង់របស់វាជាកម្មសិទ្ធិ (ប្រសិនបើប្រភេទខុសគ្នា នោះអ្នកសម្រេចចិត្តពីរបៀបបកស្រាយលទ្ធផលនៃការវាយតម្លៃរបស់ប្រតិបត្តិករ)។

ផ្ទុកលើសទម្ងន់ប្រតិបត្តិករ unary

សូមក្រឡេកមើលឧទាហរណ៍នៃការផ្ទុកលើសចំណុះនៃប្រតិបត្តិករ unary សម្រាប់ថ្នាក់ចំនួនគត់ដែលបានកំណត់ខាងលើ។ ក្នុងពេលជាមួយគ្នានេះ ចូរយើងកំណត់ពួកវាក្នុងទម្រង់នៃមុខងារមិត្តភាព ហើយពិចារណាពីប្រតិបត្តិករបន្ថយ និងបង្កើន៖
ចំនួនគត់ថ្នាក់ (ឯកជន៖ តម្លៃ int; សាធារណៈ៖ ចំនួនគត់(int i): តម្លៃ(i) () //unary + friend const ចំនួនគត់&ប្រតិបត្តិករ+(const ចំនួនគត់&i); //unary - friend const ចំនួនគត់ប្រតិបត្តិករ-(const ចំនួនគត់&i) ; //prefix increment friend const Integer& operator ++(ចំនួនគត់&i); //postfix increment friend const Integer operator++(Integer&i, int); //prefix decrement friend const Integer& operator--(Integer&i); ខ្ញុំ, int); //unary plus មិនធ្វើអ្វីទាំងអស់។ const Integer& operator+(const Integer&i) ( return i.value; ) const Integer operator-(const Integer&i) ( return Integer(-i.value); ) //prefix version ត្រឡប់តម្លៃបន្ទាប់ពី increment const Integer& operator++(Integer&i) ( i.value++; return i; ) // កំណែ postfix ត្រឡប់តម្លៃមុនពេល increment const Integer operator ++(Integer&i, int) ( Integer oldValue(i.value); i.value ++; return oldValue; ) //prefix version returns តម្លៃបន្ទាប់ពី decrement const ចំនួនគត់&ប្រតិបត្តិករ--(ចំនួនគត់&i) ( i.value--; return i; ) // កំណែ postfix ត្រឡប់តម្លៃមុនពេល decrement const Integer operator--(Integer&i, int) ( Integer oldValue(i. តម្លៃ); i .value--;
ឥឡូវអ្នកដឹងពីរបៀបដែលកម្មវិធីចងក្រងបែងចែករវាងបុព្វបទ និងកំណែ postfix នៃការបន្ថយ និងបង្កើន។ ក្នុងករណីនៅពេលដែលវាឃើញកន្សោម ++i ប្រតិបត្តិករមុខងារ ++(a) ត្រូវបានហៅ។ ប្រសិនបើវាឃើញ i++ នោះ operator ++(a, int) ត្រូវបានហៅ។ នោះគឺជាមុខងារ overloaded operator++ ត្រូវបានគេហៅថា ហើយនេះគឺជាអ្វីដែល dummy int parameter នៅក្នុងកំណែ postfix ត្រូវបានប្រើសម្រាប់។

ប្រតិបត្តិករគោលពីរ

សូមក្រឡេកមើលវាក្យសម្ព័ន្ធសម្រាប់ overloading binary operators ។ ចូរយើងផ្ទុកលើសចំនួនប្រតិបត្តិករដែលត្រឡប់តម្លៃ l ប្រតិបត្តិករតាមលក្ខខណ្ឌមួយ និងប្រតិបត្តិករមួយដែលបង្កើតតម្លៃថ្មី (តោះកំណត់ពួកវាជាសកល)៖
class Integer (private: int value; public: Integer(int i): value(i) () friend const Integer operator+(const Integer&left, const Integer&right); friend Integer& operator+=(Integer&left, const Integer&right); friend bool operator==(const ចំនួនគត់&ឆ្វេង, const ចំនួនគត់&right); const Integer operator+(const Integer&left, const Integer&right) ( return Integer(left.value + right.value); ) Integer& operator+=(Integer&left, const Integer&right) (left.value += right.value; return left; ) bool operator==(const ចំនួនគត់&ឆ្វេង, const ចំនួនគត់&right) (ត្រឡប់ left.value == right.value; )
នៅក្នុងឧទាហរណ៍ទាំងអស់នេះ ប្រតិបត្តិករត្រូវបានផ្ទុកលើសទម្ងន់សម្រាប់ប្រភេទដូចគ្នា ទោះបីជាយ៉ាងណាក៏ដោយ វាមិនចាំបាច់ទេ។ ជាឧទាហរណ៍ អ្នកអាចផ្ទុកលើសចំណុះនៃប្រភេទចំនួនគត់ និងអណ្តែតរបស់យើង ដែលកំណត់ដោយភាពស្រដៀងគ្នារបស់វា។

អាគុយម៉ង់ និងតម្លៃត្រឡប់

ដូចដែលអ្នកអាចឃើញឧទាហរណ៍ប្រើវិធីផ្សេងគ្នានៃការបញ្ជូនអាគុយម៉ង់ទៅមុខងារនិងតម្លៃប្រតិបត្តិករត្រឡប់មកវិញ។
  • ប្រសិនបើអាគុយម៉ង់មិនត្រូវបានកែប្រែដោយប្រតិបត្តិករទេ ក្នុងករណីឧទាហរណ៍ unary plus វាត្រូវតែឆ្លងកាត់ជាឯកសារយោងទៅថេរមួយ។ ជាទូទៅ នេះ​ជា​ការ​ពិត​សម្រាប់​ប្រមាណវិធី​នព្វន្ធ​ស្ទើរតែ​ទាំងអស់ (បូក ដក គុណ...)
  • ប្រភេទនៃតម្លៃត្រឡប់មកវិញអាស្រ័យលើលក្ខណៈរបស់ប្រតិបត្តិករ។ ប្រសិនបើប្រតិបត្តិករត្រូវតែត្រឡប់តម្លៃថ្មី នោះវត្ថុថ្មីត្រូវតែត្រូវបានបង្កើត (ដូចក្នុងករណីបូកនឹងគោលពីរ)។ ប្រសិនបើ​អ្នក​ចង់​ការពារ​វត្ថុ​ពី​ការ​កែប្រែ​ជា l-value នោះ​អ្នក​ត្រូវ​ត្រឡប់​វា​ជា​ថេរ។
  • ប្រតិបត្តិករកិច្ចការត្រូវតែត្រឡប់សេចក្តីយោងទៅធាតុដែលបានផ្លាស់ប្តូរ។ ផងដែរ ប្រសិនបើអ្នកចង់ប្រើ assignment operator ក្នុង constructs ដូចជា (x=y).f() ដែលអនុគមន៍ f() ត្រូវបានហៅសម្រាប់ variable x បន្ទាប់ពីកំណត់វាទៅ y បន្ទាប់មកកុំត្រឡប់សេចក្តីយោងទៅ ថេរ គ្រាន់តែត្រឡប់ឯកសារយោង។
  • ប្រតិបត្តិករឡូជីខលគួរតែត្រឡប់ int នៅអាក្រក់បំផុត និង bool ល្អបំផុត។

ត្រឡប់តម្លៃបង្កើនប្រសិទ្ធភាព

នៅពេលបង្កើតវត្ថុថ្មី និងបញ្ជូនពួកវាមកវិញពីមុខងារមួយ អ្នកគួរតែប្រើសញ្ញាណដែលស្រដៀងនឹងឧទាហរណ៍នៃ binary plus operator ដែលបានពិពណ៌នាខាងលើ។
ត្រឡប់ចំនួនគត់(left.value + right.value);
និយាយឱ្យត្រង់ទៅ ខ្ញុំមិនដឹងថាស្ថានភាពបែបណាដែលពាក់ព័ន្ធសម្រាប់ C ++ 11;
នៅ glance ដំបូង វាមើលទៅស្រដៀងនឹងវាក្យសម្ព័ន្ធសម្រាប់បង្កើតវត្ថុបណ្តោះអាសន្ន ពោលគឺវាហាក់ដូចជាមិនមានភាពខុសគ្នារវាងកូដខាងលើ និងនេះទេ៖
ចំនួនគត់ temp(left.value + right.value); សីតុណ្ហភាពត្រឡប់មកវិញ;
ប៉ុន្តែតាមពិតក្នុងករណីនេះ អ្នកសាងសង់នឹងត្រូវបានហៅក្នុងជួរទីមួយ បន្ទាប់មកអ្នកបង្កើតច្បាប់ចម្លងនឹងត្រូវបានហៅ ដែលនឹងចម្លងវត្ថុ ហើយបន្ទាប់មកនៅពេលដែល unwinding ជង់ អ្នកបំផ្លាញនឹងត្រូវបានហៅ។ នៅពេលប្រើធាតុទីមួយ កម្មវិធីចងក្រងដំបូងបង្កើតវត្ថុនៅក្នុងអង្គចងចាំដែលវាត្រូវការចម្លង ដូច្នេះរក្សាទុកការហៅទៅអ្នកបង្កើតច្បាប់ចម្លង និងអ្នកបំផ្លាញ។

ប្រតិបត្តិករពិសេស

C ++ មានប្រតិបត្តិករដែលមានវាក្យសម្ព័ន្ធជាក់លាក់ និងវិធីសាស្ត្រផ្ទុកលើសទម្ងន់។ ឧទាហរណ៍ ប្រតិបត្តិករធ្វើលិបិក្រម។ វាតែងតែត្រូវបានកំណត់ថាជាសមាជិកនៃថ្នាក់មួយ ហើយចាប់តាំងពីវត្ថុដែលបានធ្វើលិបិក្រមមានបំណងធ្វើដូចអារេ វាគួរតែត្រឡប់សេចក្តីយោងមួយ។
សញ្ញាក្បៀស
ប្រតិបត្តិករ "ពិសេស" ក៏រួមបញ្ចូលសញ្ញាក្បៀសផងដែរ។ វា​ត្រូវ​បាន​ហៅ​លើ​វត្ថុ​ដែល​មាន​សញ្ញាក្បៀស​នៅ​ជាប់​នឹង​វា (ប៉ុន្តែ​វា​មិន​ត្រូវ​បាន​ហៅ​ក្នុង​បញ្ជី​អាគុយម៉ង់​មុខងារ)។ ការមកជាមួយករណីប្រើប្រាស់ដ៏មានអត្ថន័យសម្រាប់ប្រតិបត្តិករនេះមិនងាយស្រួលនោះទេ។ Habrauser នៅក្នុងមតិយោបល់ទៅអត្ថបទមុនអំពីការផ្ទុកលើសទម្ងន់។
ទ្រនិច​ទ្រនិច​ទ្រនិច​បង្ហាញ​ប្រតិបត្តិករ
ការផ្ទុកលើសទម្ងន់នៃប្រតិបត្តិករទាំងនេះអាចត្រូវបានរាប់ជាសុចរិតសម្រាប់ថ្នាក់ទ្រនិចឆ្លាតវៃ។ ប្រតិបត្តិករនេះត្រូវបានកំណត់ជាចាំបាច់ជាមុខងារថ្នាក់ ហើយការរឹតបន្តឹងមួយចំនួនត្រូវបានដាក់លើវា៖ វាត្រូវតែត្រឡប់វត្ថុ (ឬឯកសារយោង) ឬទ្រនិចដែលអនុញ្ញាតឱ្យចូលប្រើវត្ថុ។
ប្រតិបត្តិករចាត់តាំង
ប្រតិបត្តិករកិច្ចការត្រូវបានកំណត់ជាចាំបាច់ជាមុខងារថ្នាក់ ព្រោះវាត្រូវបានភ្ជាប់ខាងក្នុងទៅវត្ថុនៅខាងឆ្វេងនៃ "=" ។ ការកំណត់ប្រតិបត្តិករកិច្ចការជាសកលនឹងធ្វើឱ្យវាអាចបដិសេធឥរិយាបថលំនាំដើមរបស់ប្រតិបត្តិករ "=" ។ ឧទាហរណ៍៖
class Integer (private: int value; public: Integer(int i): value(i) () Integer& operator=(const Integer&right) ( //check for self-assignment if (this == &right) ( return * this; ) តម្លៃ = right.value;

ដូចដែលអ្នកអាចឃើញនៅដើមមុខងារ ការត្រួតពិនិត្យត្រូវបានបង្កើតឡើងសម្រាប់ការចាត់តាំងដោយខ្លួនឯង។ ជាទូទៅ ក្នុងករណីនេះ ការសម្រេចដោយខ្លួនឯងគឺមិនបង្កគ្រោះថ្នាក់ទេ ប៉ុន្តែស្ថានភាពមិនតែងតែសាមញ្ញនោះទេ។ ឧទាហរណ៍ ប្រសិនបើវត្ថុមានទំហំធំ អ្នកអាចខ្ជះខ្ជាយពេលវេលាច្រើនលើការចម្លងដែលមិនចាំបាច់ ឬនៅពេលធ្វើការជាមួយទ្រនិច។

ប្រតិបត្តិករដែលមិនអាចផ្ទុកលើសទម្ងន់បាន។
ប្រតិបត្តិករមួយចំនួននៅក្នុង C ++ មិនផ្ទុកលើសទម្ងន់ទាល់តែសោះ។ ជាក់ស្តែង នេះត្រូវបានធ្វើសម្រាប់ហេតុផលសុវត្ថិភាព។
  • ប្រតិបត្តិករជ្រើសរើសសមាជិកថ្នាក់ ".".
  • ប្រតិបត្តិករសម្រាប់ការបង្វែរទ្រនិចទៅសមាជិកថ្នាក់ ".*"
  • C ++ មិនមានប្រតិបត្តិករនិទស្សន្ត (ដូចនៅក្នុង Fortran) "**" ទេ។
  • វាត្រូវបានហាមឃាត់មិនឱ្យកំណត់ប្រតិបត្តិករផ្ទាល់ខ្លួនរបស់អ្នក (អាចមានបញ្ហាក្នុងការកំណត់អាទិភាព)។
  • អាទិភាពប្រតិបត្តិករមិនអាចផ្លាស់ប្តូរបានទេ។
ដូចដែលយើងបានរកឃើញរួចហើយ មានវិធីពីរយ៉ាងនៃប្រតិបត្តិករ - ជាមុខងារថ្នាក់ និងជាមុខងារសកលដែលមានលក្ខណៈមិត្តភាព។
Rob Murray នៅក្នុងសៀវភៅ C++ Strategies and Tactics របស់គាត់ កំណត់គោលការណ៍ណែនាំខាងក្រោមសម្រាប់ជ្រើសរើសទម្រង់ប្រតិបត្តិករ៖

ហេតុ​អ្វី​បាន​ជា​យ៉ាង​នេះ? ទីមួយ ប្រតិបត្តិករមួយចំនួនមានកម្រិតដំបូង។ ជាទូទៅ ប្រសិនបើមិនមានភាពខុសគ្នាតាមន័យធៀបនៅក្នុងរបៀបដែលប្រតិបត្តិករត្រូវបានកំណត់ទេនោះ វាជាការប្រសើរក្នុងការរចនាវាជាមុខងារថ្នាក់ ដើម្បីបញ្ជាក់ពីការតភ្ជាប់ ហើយលើសពីនេះទៀតមុខងារនឹងស្ថិតនៅក្នុងជួរ។ បន្ថែមពីលើនេះ ជួនកាលវាអាចមានតម្រូវការតំណាងឱ្យ operand ខាងឆ្វេងជាវត្ថុនៃថ្នាក់ផ្សេងទៀត។ ប្រហែលជាឧទាហរណ៍ដ៏គួរឱ្យចាប់អារម្មណ៍បំផុតគឺនិយមន័យឡើងវិញ<< и >> សម្រាប់ស្ទ្រីម I/O ។

អក្សរសាស្ត្រ

Bruce Eckel - ទស្សនវិជ្ជា C ++ ។ ការណែនាំអំពីស្តង់ដារ C ++ ។

ស្លាក:

  • C++
  • ប្រតិបត្តិករផ្ទុកលើសទម្ងន់
  • ប្រតិបត្តិករផ្ទុកលើសទម្ងន់
បន្ថែមស្លាក

មូលដ្ឋានគ្រឹះនៃការផ្ទុកលើសទម្ងន់របស់ប្រតិបត្តិករ

C# ដូចជាភាសាសរសេរកម្មវិធីណាមួយមានសំណុំនិមិត្តសញ្ញាដែលត្រៀមរួចជាស្រេចដែលប្រើដើម្បីអនុវត្ត ប្រតិបត្តិការមូលដ្ឋានលើប្រភេទដែលភ្ជាប់មកជាមួយ។ ឧទាហរណ៍ គេដឹងថា ប្រតិបត្តិការ + អាចត្រូវបានអនុវត្តចំពោះចំនួនគត់ពីរ ដើម្បីផ្តល់ផលបូករបស់ពួកគេ៖

// ប្រតិបត្តិការ + ជាមួយចំនួនគត់។ int a = 100; int b = 240; int c = a + b; // s ឥឡូវនេះស្មើនឹង 340

មិនមានអ្វីថ្មីនៅទីនេះទេ ប៉ុន្តែតើអ្នកធ្លាប់គិតទេថា ប្រតិបត្តិការ + ដូចគ្នាអាចត្រូវបានអនុវត្តចំពោះប្រភេទទិន្នន័យដែលភ្ជាប់មកជាមួយ C# ភាគច្រើន? ជាឧទាហរណ៍ សូមពិចារណាកូដនេះ៖

// ប្រតិបត្តិការ + ជាមួយខ្សែអក្សរ។ string si = "ជំរាបសួរ"; string s2 = "ពិភពលោក!"; ខ្សែអក្សរ s3 = si + s2; // s3 ឥឡូវនេះមាន "ជំរាបសួរពិភពលោក!"

ជាសំខាន់ មុខងារនៃប្រតិបត្តិការ + គឺផ្អែកតែលើប្រភេទទិន្នន័យដែលតំណាង (ខ្សែអក្សរ ឬចំនួនគត់ក្នុងករណីនេះ)។ នៅពេលដែលប្រតិបត្តិការ + ត្រូវបានអនុវត្តទៅ ប្រភេទលេខ, យើងទទួលបាន ផលបូកនព្វន្ធប្រតិបត្តិករ ទោះយ៉ាងណាក៏ដោយនៅពេលដែលប្រតិបត្តិការដូចគ្នាត្រូវបានអនុវត្តទៅ ប្រភេទខ្សែអក្សរយើងទទួលបានការភ្ជាប់នៃខ្សែអក្សរ។

ភាសា C# ផ្តល់នូវសមត្ថភាពក្នុងការបង្កើតថ្នាក់ពិសេស និងរចនាសម្ព័ន្ធដែលឆ្លើយតបតែមួយគត់ចំពោះសំណុំនិមិត្តសញ្ញាមូលដ្ឋានដូចគ្នា (ដូចជា + ប្រតិបត្តិករ) ។ សូមចងចាំថា រាល់ប្រតិបត្តិករ C# ដែលភ្ជាប់មកជាមួយ មិនអាចផ្ទុកលើសទម្ងន់បានទេ។ តារាងខាងក្រោមពិពណ៌នាអំពីសមត្ថភាពផ្ទុកលើសទម្ងន់នៃប្រតិបត្តិការមូលដ្ឋាន៖

ប្រតិបត្តិការ C# លទ្ធភាពនៃការផ្ទុកលើសទម្ងន់
+, -, !, ++, --, ពិត, មិនពិត សំណុំនៃប្រតិបត្តិករ unary នេះអាចផ្ទុកលើសទម្ងន់
+, -, *, /, %, &, |, ^, > ប្រតិបត្តិការគោលពីរទាំងនេះអាចផ្ទុកលើសទម្ងន់
==, !=, <, >, <=, >= ប្រតិបត្តិករប្រៀបធៀបទាំងនេះអាចផ្ទុកលើសទម្ងន់។ C# ទាមទារការផ្ទុកលើសទម្ងន់នៃប្រតិបត្តិករ "ចូលចិត្ត" (ឧ។< и >, <= и >=, == និង!=)
ប្រតិបត្តិការមិនអាចផ្ទុកលើសទម្ងន់បានទេ។ ទោះយ៉ាងណាក៏ដោយ លិបិក្រមផ្តល់មុខងារស្រដៀងគ្នា
() ប្រតិបត្តិការ () មិនអាចផ្ទុកលើសទម្ងន់បានទេ។ ទោះជាយ៉ាងណាក៏ដោយវិធីសាស្ត្របំប្លែងពិសេសផ្តល់នូវមុខងារដូចគ្នា។
+=, -=, *=, /=, %=, &=, |=, ^=, >= ប្រតិបត្តិករកិច្ចការខ្លីមិនអាចផ្ទុកលើសទម្ងន់បានទេ។ ទោះយ៉ាងណាក៏ដោយ អ្នកទទួលបានពួកវាដោយស្វ័យប្រវត្តិដោយផ្ទុកលើសទម្ងន់ប្រតិបត្តិការប្រព័ន្ធគោលពីរដែលត្រូវគ្នា។

ការផ្ទុកលើសទម្ងន់របស់ប្រតិបត្តិករគឺទាក់ទងយ៉ាងជិតស្និទ្ធទៅនឹងវិធីសាស្ត្រផ្ទុកលើសទម្ងន់។ សម្រាប់ប្រតិបត្តិការលើសទម្ងន់សូមប្រើ ពាក្យគន្លឹះ ប្រតិបត្តិករដែលកំណត់វិធីសាស្ត្រប្រតិបត្តិករ ដែលនៅក្នុងវេនកំណត់សកម្មភាពរបស់ប្រតិបត្តិករទាក់ទងទៅនឹងថ្នាក់របស់វា។ មានពីរទម្រង់នៃវិធីសាស្រ្តប្រតិបត្តិករ៖ មួយសម្រាប់ប្រតិបត្តិករ unary, មួយទៀតសម្រាប់ binary operators ។ ខាងក្រោមនេះជាទម្រង់ទូទៅសម្រាប់បំរែបំរួលនីមួយៗនៃវិធីសាស្ត្រទាំងនេះ៖

// ទម្រង់ទូទៅប្រតិបត្តិករ unary ផ្ទុកលើសទម្ងន់។ public static return_type operator op(parameter_type operand) ( // operations ) // ទម្រង់ទូទៅនៃការផ្ទុកលើសទម្ងន់នៃប្រតិបត្តិករប្រព័ន្ធគោលពីរ។ public static return_type operator op(parameter_type1 operand1, parameter_type2 operand2) ( // operations )

នៅទីនេះ op ត្រូវបានជំនួសដោយប្រតិបត្តិករផ្ទុកលើសទម្ងន់ ឧទាហរណ៍ + ឬ / និង return_typeតំណាងឱ្យ ប្រភេទជាក់លាក់តម្លៃត្រឡប់ដោយប្រតិបត្តិការដែលបានបញ្ជាក់។ តម្លៃនេះអាចជាប្រភេទណាមួយ ប៉ុន្តែជារឿយៗត្រូវបានបញ្ជាក់ជាប្រភេទដូចគ្នាទៅនឹងថ្នាក់ដែលប្រតិបត្តិករផ្ទុកលើសទម្ងន់។ ការជាប់ទាក់ទងគ្នានេះធ្វើឱ្យវាកាន់តែងាយស្រួលក្នុងការប្រើប្រតិបត្តិករលើសទម្ងន់នៅក្នុងកន្សោម។ សម្រាប់ប្រតិបត្តិករ unary ប្រតិបត្តិករតំណាងឱ្យ operand ដែលត្រូវបានឆ្លងកាត់ ហើយសម្រាប់ binary operators ដូចគ្នានេះត្រូវបានតំណាង ប្រតិបត្តិករ ១និង ប្រតិបត្តិការ ២. ចំណាំថាវិធីសាស្ត្រប្រតិបត្តិករត្រូវតែមានទាំងឧបករណ៍បញ្ជាក់ប្រភេទសាធារណៈ និងឋិតិវន្ត។

ផ្ទុកលើសទម្ងន់ប្រតិបត្តិករប្រព័ន្ធគោលពីរ

សូមក្រឡេកមើលការប្រើប្រាស់ binary operator overloading ដោយប្រើឧទាហរណ៍សាមញ្ញ៖

ការប្រើប្រាស់ប្រព័ន្ធ; ដោយប្រើ System.Collections.Generic; ដោយប្រើ System.Linq; ដោយប្រើ System.Text; namespace ConsoleApplication1 ( ថ្នាក់ MyArr ( // សំរបសំរួលនៃចំណុចមួយនៅក្នុងលំហបីវិមាត្រសាធារណៈ int x, y, z; សាធារណៈ MyArr (int x = 0, int y = 0, int z = 0) ( this.x = x; this.y = y; this.z = z; ប្រតិបត្តិករគោលពីរ+ ប្រតិបត្តិករ MyArr ឋិតិវន្តសាធារណៈ +(MyArr obj1, MyArr obj2) ( MyArr arr = ថ្មី MyArr(); arr.x = obj1.x + obj2.x; arr.y = obj1.y + obj2.y; arr.z = obj1.z + obj2.z; ត្រឡប់ arr; ) // Overload the binary operator - public static MyArr operator -(MyArr obj1, MyArr obj2) ( MyArr arr = new MyArr(); arr.x = obj1.x - obj2. x ; arr.y = obj1.y - obj2.y; arr.z = obj1.z - obj2.z ត្រឡប់ arr; , -4); WriteLine("កូអរដោនេនៃចំណុចទីមួយ៖ " +Point1.x + " " + Point1.y + " " + Point1.z); .y + " " + Point2.z + "\n"); MyArr Point3 = Point1 + Point2; = " + Point3.x + " " + Point3.y + " " + Point3.z); Point3 = Point1 - Point2 ; Console.WriteLine("\nPoint1 - Point2 = " + Point3.x + " " + Point3.y + " " + Point3.z);

ផ្ទុកលើសទម្ងន់ប្រតិបត្តិករ unary

ប្រតិបត្តិករ Unary ត្រូវ​បាន​ផ្ទុក​លើស​ទម្ងន់​ដូច​គ្នា​នឹង​ប្រតិបត្តិករ​គោលពីរ។ ភាពខុសគ្នាចំបង ពិតណាស់គឺថាពួកគេមានតែមួយ operand ។ តោះធ្វើទំនើបកម្មឧទាហរណ៍មុនដោយបន្ថែម operator overloads ++,--, -:

ការប្រើប្រាស់ប្រព័ន្ធ; ដោយប្រើ System.Collections.Generic; ដោយប្រើ System.Linq; ដោយប្រើ System.Text; namespace ConsoleApplication1 ( ថ្នាក់ MyArr ( // សំរបសំរួលនៃចំណុចមួយនៅក្នុងលំហបីវិមាត្រសាធារណៈ int x, y, z; សាធារណៈ MyArr (int x = 0, int y = 0, int z = 0) ( this.x = x; this.y = y; this.z = z; ) // Overload the binary operator + public static MyArr operator +(MyArr obj1, MyArr obj2) ( MyArr arr = new MyArr(); arr.x = obj1.x + obj2 .x; arr. y = obj1.y + obj2.y; arr.z = obj1.z + obj2.z ត្រឡប់ arr; ( MyArr arr = ថ្មី MyArr (); arr.x = obj1.x - obj2.x; arr.y = obj1.y - obj2.y; arr.z = obj1.z - obj2.z ) // ផ្ទុកលើសទម្ងន់ ប្រតិបត្តិករ - ប្រតិបត្តិករ MyArr ឋិតិវន្តសាធារណៈ -(MyArr obj1) ( MyArr arr = ថ្មី MyArr(); arr.x = -obj1.x; arr.y = -obj1.y; arr.z = -obj1.z; ត្រឡប់ arr; ) // ការផ្ទុកលើសចំណុះនៃប្រតិបត្តិករ unary ++ ប្រតិបត្តិករ MyArr ឋិតិវន្តសាធារណៈ ++(MyArr obj1) ( obj1.x += 1; obj1.y += 1; obj1.z +=1; ត្រឡប់ obj1; ) // ការផ្ទុកលើសទម្ងន់ unary ប្រតិបត្តិករ -- ប្រតិបត្តិករ MyArr ឋិតិវន្តសាធារណៈ --(MyArr obj1) ( obj1.x -= 1;

obj1.y -= 1;

obj1.z -= 1;

ត្រឡប់ obj1;

ប្រសិនបើអនុគមន៍ប្រតិបត្តិករត្រូវបានកំណត់ថាជាអនុគមន៍ដាច់ដោយឡែក ហើយមិនមែនជាសមាជិកនៃថ្នាក់ នោះចំនួននៃប៉ារ៉ាម៉ែត្រនៃអនុគមន៍បែបនេះគឺដូចគ្នាទៅនឹងចំនួននៃ operand របស់ប្រតិបត្តិករ។ ឧទាហរណ៍ អនុគមន៍​ដែល​តំណាង​ឱ្យ​ប្រតិបត្តិករ​ឯកតា​នឹង​មាន​ប៉ារ៉ាម៉ែត្រ​មួយ ហើយ​អនុគមន៍​ដែល​តំណាង​ឱ្យ​ប្រតិបត្តិករ​គោលពីរ​នឹង​មាន​ប៉ារ៉ាម៉ែត្រ​ពីរ។ ប្រសិនបើប្រតិបត្តិករយក operand ពីរ នោះ operand ទីមួយត្រូវបានបញ្ជូនទៅប៉ារ៉ាម៉ែត្រទីមួយនៃអនុគមន៍ ហើយ operand ទីពីរត្រូវបានបញ្ជូនទៅប៉ារ៉ាម៉ែត្រទីពីរ។ ក្នុងករណីនេះ យ៉ាងហោចណាស់ប៉ារ៉ាម៉ែត្រមួយត្រូវតែតំណាងឱ្យប្រភេទថ្នាក់

សូមក្រឡេកមើលឧទាហរណ៍ជាមួយ Counter class ដែលតំណាងឱ្យនាឡិកាបញ្ឈប់ និងរក្សាទុកចំនួនវិនាទី៖

# រួមបញ្ចូល << seconds << " seconds" << std::endl; } int seconds; }; Counter operator + (Counter c1, Counter c2) { return Counter(c1.seconds + c2.seconds); } int main() { Counter c1(20); Counter c2(10); Counter c3 = c1 + c2; c3.display(); // 30 seconds return 0; }

នៅទីនេះ មុខងារប្រតិបត្តិករមិនមែនជាផ្នែកនៃ Counter class ហើយត្រូវបានកំណត់នៅខាងក្រៅវា។ មុខងារនេះផ្ទុកលើសចំនួនប្រតិបត្តិករបន្ថែមសម្រាប់ប្រភេទបញ្ជរ។ វាជាប្រព័ន្ធគោលពីរ ដូច្នេះវាត្រូវការប៉ារ៉ាម៉ែត្រពីរ។ ក្នុងករណីនេះ យើងកំពុងបន្ថែមវត្ថុ Counter ពីរ។ អនុគមន៍នេះក៏ត្រឡប់វត្ថុ Counter ដែលរក្សាទុកចំនួនវិនាទីសរុបផងដែរ។ នោះហើយជាខ្លឹមសារ ប្រតិបត្តិការបន្ថែមនៅទីនេះចុះមកដើម្បីបន្ថែមវិនាទីនៃវត្ថុទាំងពីរ៖

Counter operator + (Counter c1, Counter c2) ( return Counter(c1.seconds + c2.seconds); )

វាមិនចាំបាច់ក្នុងការត្រឡប់វត្ថុថ្នាក់ទេ។ វាក៏អាចជាវត្ថុនៃប្រភេទបុព្វកាលដែលភ្ជាប់មកជាមួយផងដែរ។ ហើយ​យើង​ក៏​អាច​កំណត់​ការ​ផ្ទុក​លើស​ចំណុះ​របស់​ប្រតិបត្តិករ​បន្ថែម​ផងដែរ៖

int operator + (Counter c1, int s) ( return c1.seconds + s; )

កំណែនេះបន្ថែមវត្ថុ Counter ទៅលេខ ហើយត្រឡប់លេខផងដែរ។ ដូច្នេះ operand ខាងឆ្វេងនៃប្រតិបត្តិការត្រូវតែជាប្រភេទ Counter ហើយ operand ខាងស្តាំត្រូវតែជាប្រភេទ int ។ ហើយជាឧទាហរណ៍ យើងអាចអនុវត្តកំណែរបស់ប្រតិបត្តិករនេះដូចខាងក្រោម៖

បញ្ជរ c1(20); int វិនាទី = c1 + 25; // 45 std::cout<< seconds << std::endl;

ដូចគ្នានេះផងដែរ មុខងារប្រតិបត្តិករអាចត្រូវបានកំណត់ថាជាសមាជិកនៃថ្នាក់។ ប្រសិនបើអនុគមន៍ប្រតិបត្តិករត្រូវបានកំណត់ថាជាសមាជិកនៃថ្នាក់ នោះ operand ខាងឆ្វេងអាចចូលប្រើបានតាមរយៈទ្រនិចនេះ ហើយតំណាងឱ្យវត្ថុបច្ចុប្បន្ន ហើយ operand ខាងស្តាំត្រូវបានបញ្ជូនទៅមុខងារស្រដៀងគ្នាជាប៉ារ៉ាម៉ែត្រតែមួយគត់៖

# រួមបញ្ចូល class Counter (សាធារណៈ៖ Counter(int sec) ( seconds = sec; ) void display() ( std::cout<< seconds << " seconds" << std::endl; } Counter operator + (Counter c2) { return Counter(this->វិនាទី + c2.seconds);

) int operator + (int s) ( return this-> second + s; ) int វិនាទី; ); int main() ( Counter c1(20); Counter c2(10); Counter c3 = c1 + c2; c3.display(); // 30 វិនាទី int seconds = c1 + 25; // 45 ត្រឡប់ 0; )

តើប្រតិបត្តិករណាខ្លះគួរតែត្រូវបានកំណត់ឡើងវិញនៅកន្លែងណា? ប្រតិបត្តិករនៃ assignment, indexing (), calling (()), access a class member by pointer (->) គួរតែត្រូវបានកំណត់ថាជា class member functions។ ប្រតិបត្តិករដែលផ្លាស់ប្តូរស្ថានភាពរបស់វត្ថុ ឬត្រូវបានភ្ជាប់ដោយផ្ទាល់ជាមួយវត្ថុ (បង្កើន ការបន្ថយ) ជាធម្មតាក៏ត្រូវបានកំណត់ថាជាមុខងារសមាជិកថ្នាក់ផងដែរ។ ប្រតិបត្តិករផ្សេងទៀតទាំងអស់ត្រូវបានកំណត់ជាញឹកញាប់ថាជាមុខងារបុគ្គលជាជាងសមាជិកនៃថ្នាក់មួយ។

ប្រតិបត្តិករប្រៀបធៀប

ប្រតិបត្តិករមួយចំនួនត្រូវបានផ្ទុកលើសទម្ងន់ជាគូ។ ឧទាហរណ៍ ប្រសិនបើយើងកំណត់សញ្ញា == operator នោះយើងក៏ត្រូវកំណត់ operator != ផងដែរ។ ហើយនៅពេលកំណត់ប្រតិបត្តិករ< надо также определять функцию для оператора >. ឧទាហរណ៍ ចូរយើងផ្ទុកលើសទម្ងន់ប្រតិបត្តិករទាំងនេះ៖

Bool operator == (Counter c1, Counter c2) ( return c1.seconds == c2.seconds; ) bool operator != (Counter c1, Counter c2) ( return c1.seconds != c2.seconds; ) bool operator > ( Counter c1, Counter c2) ( return c1.seconds > c2.seconds; ) bool operator< (Counter c1, Counter c2) { return c1.seconds < c2.seconds; } int main() { Counter c1(20); Counter c2(10); bool b1 = c1 == c2; // false bool b2 = c1 >c2; // true std::cout<< b1 << std::endl; std::cout << b2 << std::endl; return 0; }

ប្រតិបត្តិករចាត់តាំង

# រួមបញ្ចូល class Counter (សាធារណៈ៖ Counter(int sec) ( seconds = sec; ) void display() ( std::cout<< seconds << " seconds" << std::endl; } Counter& operator += (Counter c2) { seconds += c2.seconds; return *this; } int seconds; }; int main() { Counter c1(20); Counter c2(10); c1 += c2; c1.display(); // 30 seconds return 0; }

ប្រតិបត្តិការបង្កើន និងបន្ថយ

ការកំណត់​ប្រតិបត្តិករ​បង្កើន និង​បន្ថយ​ឡើងវិញ​អាច​ជា​បញ្ហា​ប្រឈម​ជាពិសេស ដោយសារ​យើង​ត្រូវ​កំណត់​ទាំង​ទម្រង់​បុព្វបទ និង​ទម្រង់​ក្រោយ​សម្រាប់​ប្រតិបត្តិករ​ទាំងនេះ។ ចូរកំណត់ប្រតិបត្តិករស្រដៀងគ្នាសម្រាប់ប្រភេទ Counter៖

# រួមបញ្ចូល class Counter (សាធារណៈ៖ Counter(int sec) ( seconds = sec; ) void display() ( std::cout<< seconds << " seconds" << std::endl; } // префиксные операторы Counter& operator++ () { seconds += 5; return *this; } Counter& operator-- () { seconds -= 5; return *this; } // постфиксные операторы Counter operator++ (int) { Counter prev = *this; ++*this; return prev; } Counter operator-- (int) { Counter prev = *this; --*this; return prev; } int seconds; }; int main() { Counter c1(20); Counter c2 = c1++; c2.display(); // 20 seconds c1.display(); // 25 seconds --c1; c1.display(); // 20 seconds return 0; }

Counter& operator++ () (វិនាទី += 5; ត្រឡប់ * នេះ; )

នៅក្នុងមុខងារខ្លួនវា អ្នកអាចកំណត់តក្កវិជ្ជាមួយចំនួនសម្រាប់ការបង្កើនតម្លៃ។ ក្នុងករណីនេះចំនួនវិនាទីកើនឡើង 5 ។

ប្រតិបត្តិករ Postfix ត្រូវតែត្រឡប់តម្លៃនៃវត្ថុមុនការបង្កើន ពោលគឺស្ថានភាពមុនរបស់វត្ថុ។ ដើម្បីធ្វើឱ្យទម្រង់ postfix ខុសពីទម្រង់បុព្វបទ កំណែ postfix ទទួលបានប៉ារ៉ាម៉ែត្របន្ថែមនៃ type int ដែលមិនត្រូវបានប្រើ។ ទោះបីជាជាគោលការណ៍យើងអាចប្រើវាបាន។

Counter operator ++ (int) ( Counter prev = *this; ++* this; return prev;)