ថ្ងៃល្អ!
បំណងប្រាថ្នាចង់សរសេរអត្ថបទនេះបានលេចឡើងបន្ទាប់ពីបានអានការបង្ហោះ 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>> ផ្លាស់ប្តូរអាគុយម៉ង់ខាងឆ្វេងរួចហើយ។
ប្រតិបត្តិករ ==, !=
- សមីការ៖ តេស្តសម្រាប់សមភាព/វិសមភាព។ អត្ថន័យនៃសមភាពប្រែប្រួលយ៉ាងខ្លាំងទៅតាមថ្នាក់។ ក្នុងករណីណាក៏ដោយ ពិចារណាលើលក្ខណៈសម្បត្តិនៃសមភាពដូចខាងក្រោមៈ
- ការឆ្លុះបញ្ចាំង, i.e. ក == ក។
- ស៊ីមេទ្រី, i.e. ប្រសិនបើ a == b បន្ទាប់មក b == a ។
- អន្តរកាល, 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 ដែលតំណាងឱ្យនាឡិកាបញ្ឈប់ និងរក្សាទុកចំនួនវិនាទី៖
# រួមបញ្ចូល
នៅទីនេះ មុខងារប្រតិបត្តិករមិនមែនជាផ្នែកនៃ 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 ខាងស្តាំត្រូវបានបញ្ជូនទៅមុខងារស្រដៀងគ្នាជាប៉ារ៉ាម៉ែត្រតែមួយគត់៖
# រួមបញ្ចូល
) 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; }
ប្រតិបត្តិករចាត់តាំង
# រួមបញ្ចូល
ប្រតិបត្តិការបង្កើន និងបន្ថយ
ការកំណត់ប្រតិបត្តិករបង្កើន និងបន្ថយឡើងវិញអាចជាបញ្ហាប្រឈមជាពិសេស ដោយសារយើងត្រូវកំណត់ទាំងទម្រង់បុព្វបទ និងទម្រង់ក្រោយសម្រាប់ប្រតិបត្តិករទាំងនេះ។ ចូរកំណត់ប្រតិបត្តិករស្រដៀងគ្នាសម្រាប់ប្រភេទ Counter៖
# រួមបញ្ចូល
Counter& operator++ () (វិនាទី += 5; ត្រឡប់ * នេះ; )
នៅក្នុងមុខងារខ្លួនវា អ្នកអាចកំណត់តក្កវិជ្ជាមួយចំនួនសម្រាប់ការបង្កើនតម្លៃ។ ក្នុងករណីនេះចំនួនវិនាទីកើនឡើង 5 ។
ប្រតិបត្តិករ Postfix ត្រូវតែត្រឡប់តម្លៃនៃវត្ថុមុនការបង្កើន ពោលគឺស្ថានភាពមុនរបស់វត្ថុ។ ដើម្បីធ្វើឱ្យទម្រង់ postfix ខុសពីទម្រង់បុព្វបទ កំណែ postfix ទទួលបានប៉ារ៉ាម៉ែត្របន្ថែមនៃ type int ដែលមិនត្រូវបានប្រើ។ ទោះបីជាជាគោលការណ៍យើងអាចប្រើវាបាន។
Counter operator ++ (int) ( Counter prev = *this; ++* this; return prev;)