ოპერატორების გადაფარვა შესაძლებელია მონაცემთა არსებული ტიპებისთვის. ოპერაციის გადატვირთვა. როდის უნდა გადატვირთოთ ოპერატორები

უახლესი განახლება: 12.08.2018

მეთოდებთან ერთად შეგვიძლია ოპერატორების გადატვირთვაც. მაგალითად, ვთქვათ, გვაქვს შემდეგი Counter კლასი:

კლასის მრიცხველი ( საჯარო int მნიშვნელობა (მიღება; დაყენება; ))

ეს კლასი წარმოადგენს მრიცხველს, რომლის მნიშვნელობა ინახება Value თვისებაში.

და ვთქვათ, გვაქვს ორი Counter კლასის ობიექტი - ორი მრიცხველი, რომლებიც გვინდა შევადაროთ ან დავამატოთ მათი Value თვისების მიხედვით, გამოყენებით სტანდარტული ოპერაციებიშედარება და დამატებები:

მრიცხველი c1 = ახალი მრიცხველი (მნიშვნელობა = 23); მრიცხველი c2 = ახალი მრიცხველი (მნიშვნელობა = 45); bool შედეგი = c1 > c2; მრიცხველი c3 = c1 + c2;

მაგრამ მომენტშიარც შედარება და არც დამატება არ არის ხელმისაწვდომი Counter ობიექტებისთვის. ეს ოპერაციები შეიძლება გამოყენებულ იქნას მრავალი პრიმიტიული ტიპები. მაგალითად, ნაგულისხმევად შეგვიძლია დავამატოთ რიცხვითი მნიშვნელობები, მაგრამ როგორ დავამატოთ ობიექტები რთული ტიპები- შემდგენელმა არ იცის კლასები და სტრუქტურები. და ამისთვის ჩვენ გვჭირდება გადატვირთვა ოპერატორები, რომლებიც გვჭირდება.

ოპერატორის გადატვირთვა შედგება სპეციალური მეთოდის განსაზღვრისგან კლასში, რომლის ობიექტებისთვისაც გვინდა განვსაზღვროთ ოპერატორი:

საჯარო სტატიკური return_type ოპერატორი (პარამეტრები) ( )

ამ მეთოდს უნდა ჰქონდეს საჯარო სტატიკური მოდიფიკატორები, რადგან ოპერატორის გადატვირთვა გამოყენებული იქნება ყველა ობიექტისთვის ამ კლასის. შემდეგ მოდის დაბრუნების ტიპის სახელი. დაბრუნების ტიპი წარმოადგენს ტიპს, რომლის ობიექტების მიღება გვინდა. მაგალითად, ორი Counter ობიექტის დამატების შედეგად, ჩვენ ველოდებით ახალი Counter ობიექტის მიღებას. და ამ ორის შედარების შედეგად, ჩვენ გვინდა მივიღოთ bool ტიპის ობიექტი, რომელიც მიუთითებს თუ არა პირობითი გამოხატულებაან ყალბი. მაგრამ დავალებიდან გამომდინარე, დაბრუნების ტიპები შეიძლება იყოს ნებისმიერი.

შემდეგ მეთოდის ნაცვლად მიდის სახელი საკვანძო სიტყვაოპერატორი და თავად ოპერატორი. შემდეგ კი პარამეტრები ჩამოთვლილია ფრჩხილებში. ორობითი ოპერატორები იღებენ ორ პარამეტრს, უნარული ოპერატორები იღებენ ერთ პარამეტრს. და ნებისმიერ შემთხვევაში, ერთ-ერთი პარამეტრი უნდა იყოს ტიპი - კლასი ან სტრუქტურა, რომელშიც ოპერატორი არის განსაზღვრული.

მაგალითად, გადავტვირთოთ რამდენიმე ოპერატორი Counter კლასისთვის:

კლასის მრიცხველი ( public int მნიშვნელობა ( get; set; ) public static Counter ოპერატორი +(Counter c1, Counter c2) ( დააბრუნეთ ახალი მრიცხველი ( Value = c1.Value + c2.Value ); ) public static bool ოპერატორი >(Counter c1, მრიცხველი c2) ( return c1.Value > c2.Value; ) public static bool ოპერატორი<(Counter c1, Counter c2) { return c1.Value < c2.Value; } }

ვინაიდან ყველა გადატვირთული ოპერატორი ორობითია, ანუ ისინი შესრულებულია ორ ობიექტზე, თითოეული გადატვირთვისთვის არის ორი პარამეტრი.

ვინაიდან მიმატების ოპერაციის შემთხვევაში გვინდა დავამატოთ Counter კლასის ორი ობიექტი, ოპერატორი იღებს ამ კლასის ორ ობიექტს. და რადგან ჩვენ გვინდა მივიღოთ ახალი Counter ობიექტი დამატების შედეგად, ეს კლასი ასევე გამოიყენება როგორც დაბრუნების ტიპი. ამ ოპერატორის ყველა მოქმედება მოდის ახალი ობიექტის შექმნამდე, რომლის Value თვისება აერთიანებს ორივე პარამეტრის Value თვისების მნიშვნელობებს:

საჯარო სტატიკური მრიცხველის ოპერატორი +(მრიცხველი c1, მრიცხველი c2) ( დააბრუნეთ ახალი მრიცხველი (მნიშვნელობა = c1.მნიშვნელობა + c2.მნიშვნელობა); )

ასევე განისაზღვრა ორი შედარების ოპერატორი. თუ ამ შედარების ოპერატორებიდან ერთ-ერთს გადავაჭარბებთ, ამ ოპერატორებიდან მეორესაც უნდა გადავუსვათ. შედარების ოპერატორები თავად ადარებენ Value თვისებების მნიშვნელობებს და, შედარების შედეგიდან გამომდინარე, აბრუნებენ როგორც true, ასევე false.

ახლა ჩვენ ვიყენებთ გადატვირთულ ოპერატორებს პროგრამაში:

Static void Main(string args) ( Counter c1 = new Counter ( Value = 23 ); Counter c2 = new Counter ( Value = 45 ); Bool შედეგი = c1 > c2; Console.WriteLine (შედეგი); // false Counter c3 = c1 + c2 Console.WriteLine(c3.Value);

აღსანიშნავია, რომ ვინაიდან ოპერატორის განმარტება არსებითად მეთოდია, ჩვენ ასევე შეგვიძლია გადავტვირთოთ ეს მეთოდი, ანუ შევქმნათ მისთვის სხვა ვერსია. მაგალითად, დავუმატოთ სხვა ოპერატორი Counter კლასს:

საჯარო სტატიკური int ოპერატორი +(მრიცხველი c1, int val) ( დააბრუნებს c1.Value + val; )

ეს მეთოდი ამატებს Value თვისების მნიშვნელობას და გარკვეულ რიცხვს, აბრუნებს მათ ჯამს. ჩვენ ასევე შეგვიძლია გამოვიყენოთ ეს ოპერატორი:

მრიცხველი c1 = ახალი მრიცხველი (მნიშვნელობა = 23); int d = c1 + 27; // 50 Console.WriteLine(d);

გასათვალისწინებელია, რომ გადატვირთვისას არ უნდა შეიცვალოს ის ობიექტები, რომლებიც გადაეცემა ოპერატორს პარამეტრების საშუალებით. მაგალითად, ჩვენ შეგვიძლია განვსაზღვროთ increment ოპერატორი Counter კლასისთვის:

საჯარო სტატიკური მრიცხველის ოპერატორი ++(მრიცხველი c1) (c1.მნიშვნელობა += 10; დაბრუნება c1; )

ვინაიდან ოპერატორი უნირია, მას სჭირდება მხოლოდ ერთი პარამეტრი - იმ კლასის ობიექტი, რომელშიც ამ ოპერატორსგანსაზღვრული მაგრამ ეს არის ნამატის არასწორი განმარტება, რადგან ოპერატორმა არ უნდა შეცვალოს მისი პარამეტრების მნიშვნელობები.

და დამატებითი ოპერატორის უფრო სწორი გადატვირთვა ასე გამოიყურება:

საჯარო სტატიკური მრიცხველის ოპერატორი ++(მრიცხველი c1) ( დააბრუნეთ ახალი მრიცხველი ( მნიშვნელობა = c1.მნიშვნელობა + 10 ); )

ანუ, დაბრუნდება ახალი ობიექტი, რომელიც შეიცავს მნიშვნელობას Value თვისებაში.

ამ შემთხვევაში, ჩვენ არ გვჭირდება ცალკე ოპერატორების განსაზღვრა პრეფიქსის და პოსტფიქსის ზრდისთვის (ისევე, როგორც შემცირება), რადგან ერთი იმპლემენტაცია იმუშავებს ორივე შემთხვევაში.

მაგალითად, ჩვენ ვიყენებთ პრეფიქსის გაზრდის ოპერაციას:

მრიცხველი = new Counter() ( მნიშვნელობა = 10 ); Console.WriteLine($"(counter.Value)"); // 10 Console.WriteLine($"((++counter).Value)"); // 20 Console.WriteLine($"(counter.Value)"); // 20

კონსოლის გამომავალი:

ახლა ჩვენ ვიყენებთ პოსტფიქსის ზრდას:

მრიცხველი = new Counter() ( მნიშვნელობა = 10 ); Console.WriteLine($"(counter.Value)"); // 10 Console.WriteLine($"((counter++).Value)"); // 10 Console.WriteLine($"(counter.Value)"); // 20

კონსოლის გამომავალი:

აღსანიშნავია ისიც, რომ ჩვენ შეგვიძლია გავაუქმოთ ჭეშმარიტი და ყალბი ოპერატორები. მაგალითად, განვსაზღვროთ ისინი Counter კლასში:

კლასის მრიცხველი ( საჯარო int მნიშვნელობა ( get; set; ) საჯარო სტატიკური bool ოპერატორი true(Counter c1) ( return c1.Value != 0; ) public static bool ოპერატორი false(Counter c1) ( return c1.Value == 0; ) // კლასის დანარჩენი შინაარსი)

ეს ოპერატორები გადატვირთულია, როდესაც გვინდა გამოვიყენოთ ამ ტიპის ობიექტი, როგორც პირობა. მაგალითად:

მრიცხველი = new Counter() ( მნიშვნელობა = 0 ); if (counter) Console.WriteLine(true); else Console.WriteLine(false);

ოპერატორების გადატვირთვისას უნდა გაითვალისწინოთ, რომ ყველა ოპერატორის გადატვირთვა არ შეიძლება. კერძოდ, ჩვენ შეგვიძლია გადატვირთოთ შემდეგი ოპერატორები:

    ერთიანი ოპერატორები +, -, !, ~, ++, --

    ორობითი ოპერატორები +, -, *, /, %

    შედარების ოპერაციები ==, !=,<, >, <=, >=

    ლოგიკური ოპერატორები &&, ||

    დავალების ოპერატორები +=, -=, *=, /=, %=

და არის მთელი რიგი ოპერატორები, რომელთა გადატვირთვა შეუძლებელია, მაგალითად, თანასწორობის ოპერატორი = ან სამეული ოპერატორი?: , ისევე როგორც რიგი სხვა.

გადატვირთული ოპერატორების სრული სია შეგიძლიათ იხილოთ msdn დოკუმენტაციაში

ოპერატორების გადატვირთვისას ასევე უნდა გვახსოვდეს, რომ ჩვენ არ შეგვიძლია შევცვალოთ ოპერატორის პრიორიტეტი ან მისი ასოციაციურობა, ჩვენ არ შეგვიძლია შევქმნათ ახალი ოპერატორიან შეცვალეთ ოპერატორების ლოგიკა ტიპებში, რაც ნაგულისხმევია .NET-ში.

ოპერატორის გადატვირთვის საფუძვლები

C#-ს, როგორც პროგრამირების ნებისმიერ ენას, აქვს მზა კომპლექტიშესასრულებლად გამოყენებული ნიშნები ძირითადი ოპერაციებიმეტი ჩაშენებული ტიპები. მაგალითად, ცნობილია, რომ + ოპერაცია შეიძლება გამოყენებულ იქნას ორ მთელ რიცხვზე მათი ჯამის მისაცემად:

// ოპერაცია + მთელი რიცხვებით. int a = 100; int b = 240; int c = a + b; //s ახლა უდრის 340-ს

აქ ახალი არაფერია, მაგრამ გიფიქრიათ ოდესმე, რომ იგივე + ოპერაცია შეიძლება გამოყენებულ იქნას C#-ში ჩაშენებული მონაცემთა ტიპების უმეტესობისთვის? მაგალითად, განიხილეთ ეს კოდი:

// ოპერაცია + სიმებით. string si = "გამარჯობა"; string s2 = "სამყარო!"; სტრიქონი s3 = si + s2; // s3 ახლა შეიცავს "Hello World!"

არსებითად, + ოპერაციის ფუნქციონალობა ცალსახად ეფუძნება წარმოდგენილი მონაცემთა ტიპებს (სტრიქონები ან მთელი რიცხვები ამ შემთხვევაში). როდესაც + ოპერაცია გამოიყენება რიცხვითი ტიპები, ვიღებთ არითმეტიკული ჯამიოპერანდები თუმცა, როდესაც იგივე ოპერაცია გამოიყენება სიმებიანი ტიპები, ვიღებთ სიმების შეერთებას.

C# ენა იძლევა შესაძლებლობას შექმნას სპეციალური კლასები და სტრუქტურები, რომლებიც ასევე ცალსახად რეაგირებენ ძირითადი ნიშნების ერთსა და იმავე კომპლექტზე (როგორც + ოპერატორი). გაითვალისწინეთ, რომ აბსოლუტურად ყველა ჩაშენებული C# ოპერატორის გადატვირთვა შეუძლებელია. შემდეგი ცხრილი აღწერს ძირითადი ოპერაციების გადატვირთვის შესაძლებლობებს:

C# ოპერაცია გადატვირთვის შესაძლებლობა
+, -, !, ++, --, მართალია, მცდარი ეს ნაკრები ერთიანი ოპერაციებიშეიძლება გადატვირთული იყოს
+, -, *, /, %, &, |, ^, > ესენი ორობითი ოპერაციებიშეიძლება გადატვირთული იყოს
==, !=, <, >, <=, >= ეს შედარების ოპერატორები შეიძლება გადატვირთული იყოს. C# მოითხოვს "like" ოპერატორების საერთო გადატვირთვას (ე.ი.< и >, <= и >=, == და!=)
ოპერაციის გადატვირთვა შეუძლებელია. თუმცა, ინდექსატორები გვთავაზობენ მსგავს ფუნქციონირებას
() () ოპერაციის გადატვირთვა შეუძლებელია. თუმცა, იგივე ფუნქციაა გათვალისწინებული სპეციალური მეთოდებიტრანსფორმაცია
+=, -=, *=, /=, %=, &=, |=, ^=, >= მოკლე დავალების ოპერატორების გადატვირთვა შეუძლებელია; თუმცა, თქვენ მათ ავტომატურად იღებთ შესაბამისი ორობითი ოპერაციის გადატვირთვით

ოპერატორის გადატვირთვა მჭიდრო კავშირშია მეთოდის გადატვირთვასთან. ოპერატორის გადატვირთვისთვის გამოიყენეთ საკვანძო სიტყვა ოპერატორი, რომელიც განსაზღვრავს ოპერატორის მეთოდს, რომელიც თავის მხრივ განსაზღვრავს ოპერატორის მოქმედებას მის კლასთან მიმართებაში. არსებობს ოპერატორის მეთოდების ორი ფორმა: ერთი უნარული ოპერატორებისთვის, მეორე ორობითი ოპერატორებისთვის. ქვემოთ მოცემულია ზოგადი ფორმა ამ მეთოდების თითოეული ვარიაციისთვის:

// ზოგადი ფორმაერთიანი ოპერატორის გადატვირთვა. public static return_type ოპერატორი op(parameter_type operand) ( // ოპერაციები ) // ორობითი ოპერატორის გადატვირთვის ზოგადი ფორმა. საჯარო სტატიკური return_type ოპერატორი op(parameter_type1 operand1, parameter_type2 operand2) ( // ოპერაციები )

აქ op ჩანაცვლებულია გადატვირთული ოპერატორით, მაგალითად + ან / და დაბრუნების_ტიპიმიუთითებს მითითებული ოპერაციით დაბრუნებული მნიშვნელობის კონკრეტულ ტიპს. ეს მნიშვნელობა შეიძლება იყოს ნებისმიერი ტიპის, მაგრამ ხშირად მითითებულია, რომ იგივე ტიპისაა კლასი, რომლისთვისაც ოპერატორი გადატვირთულია. ეს კორელაცია აადვილებს გადატვირთული ოპერატორების გამოყენებას გამონათქვამებში. ერთიანი ოპერატორებისთვის ოპერანდიაღნიშნავს გაცემულ ოპერანდს, ხოლო ბინარული ოპერატორებისთვის იგივე აღინიშნება ოპერანდი 1და ოპერანდი 2. გაითვალისწინეთ, რომ ოპერატორის მეთოდებს უნდა ჰქონდეთ როგორც საჯარო, ასევე სტატიკური ტიპის სპეციფიკატორები.

ორობითი ოპერატორების გადატვირთვა

მოდით შევხედოთ ორობითი ოპერატორის გადატვირთვის გამოყენებას მარტივი მაგალითის გამოყენებით:

სისტემის გამოყენება; 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.z = z ) // ორობითი ოპერატორის გადატვირთვა + საჯარო სტატიკური MyArr ოპერატორი +(MyArr obj1, MyArr obj2) (MyArr arr = new MyArr(); .x arr y = obj2.y.z = obj1.z + obj2.z ) // ორობითი ოპერატორის გადატვირთვა - (MyArr obj2); ( MyArr arr = ახალი MyArr (); arr.x = obj1.x - obj2.x; arr.y = obj1.y; arr.z = obj1.z - obj2.z) ) class Program ( სტატიკური სიცარიელე Main(string args) ( MyArr Point1 = new MyArr(1, 12, -4); MyArr Point2 = new MyArr(0, -3, 18); Console.WriteLine("პირველი წერტილის კოორდინატები: " + Point1.x + " " + Point1.y + " " + Point1.z. Console.WriteLine("მეორე წერტილის კოორდინატები: " + Point2.x + " " + Point2.y + " " + Point2.z + "\n); "); MyArr Point3 = Point1 + Point2; Console.WriteLine ("\nPoint1 + Point2 = " + Point3.x + " " + Point3.y + " " + Point3.z); - Point2 = " + Point3.x + " " + Point3.y + " " + Point3.z. ReadLine( ) );

ერთიანი ოპერატორების გადატვირთვა

უნარული ოპერატორები გადატვირთულია ისევე, როგორც ბინარული ოპერატორები. მთავარი განსხვავება, რა თქმა უნდა, არის ის, რომ მათ აქვთ მხოლოდ ერთი ოპერანდი. მოდით გავაუმჯობესოთ წინა მაგალითი ოპერატორის გადატვირთვების დამატებით ++, --, -:

სისტემის გამოყენება; 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.z = z ) // ორობითი ოპერატორის გადატვირთვა + საჯარო სტატიკური MyArr ოპერატორი +(MyArr obj1, MyArr obj2) (MyArr arr = new MyArr(); .x arr y = obj2.y.z = obj1.z + obj2.z ) // ორობითი ოპერატორის გადატვირთვა - (MyArr obj2); ( 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; ) // ერთიანი ოპერატორის გადატვირთვა ++ საჯარო სტატიკური MyArr ოპერატორი ++(MyArr obj1) ( obj1.x += 1; obj1.y += 1; obj1.z +=1; დაბრუნება obj1; ) // უნარის გადატვირთვა ოპერატორი -- საჯარო სტატიკური MyArr ოპერატორი --(MyArr obj1) ( obj1.x -= 1;

obj1.y -= 1;

როდესაც პროგრამა განსაზღვრავს კლასს, ის არსებითად განსაზღვრავს ახალი ტიპისმონაცემები. შემდეგ C# ენა საშუალებას გაძლევთ განსაზღვროთ ოპერაციები, რომლებიც შეესაბამება მონაცემთა ამ ახალ ტიპს.

ოპერაციის გადატვირთვამოიცავს ოპერაციის მნიშვნელობის შეცვლას კონკრეტულ კლასთან გამოყენებისას.

მაგალითად, იყოს:

myclass a,bc;…//a,b,c-კლასის myclass-ის შემთხვევები

c=a+b; // გადატვირთული ოპერაციადამატება კლასის myclass-ისთვის

ოპერატორის გადატვირთვა ჩვეულებრივ გამოიყენება კლასებისთვის, რომლებიც აღწერს მათემატიკურ ან ფიზიკურ ცნებებს, ანუ კლასებს, რომლებისთვისაც საჭიროა შესაბამისი ოპერაციების შესრულება.

გადატვირთული ოპერაციის გამოცხადების ზოგადი სინტაქსია:

[ატრიბუტები] სპეციფიკაციებიოპერატორისაოპერაციო ორგანო,

სპეციფიკატორები - საჯარო, სტატიკური, გარე

ოპერატორი – საკვანძო სიტყვა, რომელიც განსაზღვრავს გადატვირთულ ოპერაციას

ოპერაციული ორგანო - მოქმედებები, რომლებიც შესრულებულია ექსპრესიაში ოპერაციის გამოყენებისას

მხოლოდ სტანდარტული ოპერაციების გადატვირთვა შეიძლება.

ოპერაციის გადატვირთვის ალგორითმი:

    განსაზღვრეთ კლასი, რომელსაც ამ ოპერაციასდაინიშნება.

    საკვანძო სიტყვა გამოიყენება ოპერაციების გადატვირთვისთვის ოპერატორი.

    როდესაც თქვენ უგულებელყოფთ ოპერაციას, უნდა მიუთითოთ მეთოდი, რომელსაც C# გამოიძახებს ყოველ ჯერზე, როცა კლასი იყენებს გადატვირთულ ოპერაციას.

ეს მეთოდი, თავის მხრივ, ასრულებს შესაბამის ოპერაციას.:

    ოპერაციის გადატვირთვის წესები

    ოპერაცია უნდა გამოცხადდეს საჯარო სტატიკური

    ოპერაციის პარამეტრები უნდა გადავიდეს მნიშვნელობით (არა ref, არა out)

კლასში არ უნდა იყოს ორი იდენტური გადატვირთული ოპერატორი. თუ პროგრამა გადატვირთავს ოპერაციას კონკრეტული კლასისთვის, მაშინ ამ ოპერაციის მნიშვნელობა იცვლება მხოლოდ მითითებული კლასისთვის

, პროგრამის დანარჩენი ნაწილი გააგრძელებს ამ ოპერაციის გამოყენებას მისი სტანდარტული მოქმედებების შესასრულებლად.

ერთიანი ოპერატორების გადატვირთვა

    Unary ოპერატორები, რომლებიც შეიძლება გადატვირთული იყოს C#-ში, მოიცავს:

    ერთიანი + და -

    ლოგიკურია!,

true, false – ჩვეულებრივ გადატვირთულია SQL ტიპისთვის

გადატვირთული უნარი ოპერატორის გამოცხადების სინტაქსია:საჯაროსტატიკურიოპერატორიtype_return_value

unary_operation (ერთი პარამეტრი),

სადაც პარამეტრი არის კლასი, რომლისთვისაც ეს ოპერაცია გადატვირთულია

მაგალითად,

საჯარო სტატიკური myclass ოპერატორი ++(myclass x)

საჯარო სტატიკური int ოპერატორი +(myclass x)

საჯარო სტატიკური bool ოპერატორი true (myclass x)

    გადატვირთული ოპერაცია ბრუნდება:

    unary + და –, ! ნებისმიერი სახის რაოდენობა

    კლასის ტიპის ღირებულება

true, false – bool ტიპის მნიშვნელობა

პრეფიქსი და პოსტფიქსი ++ და – არ განსხვავდება გადატვირთვისას.

ერთიანი ოპერაციების გადატვირთვის მაგალითი კლასის მაგალითის გამოყენებითერთგანზომილებიანი

მასივი

a=new int;

საჯარო MyArray ( პარამები int mas)

სიგრძე =მას.სიგრძე;

a=new int;

for (int i=0;i

საჯარო სტატიკური MyArray ოპერატორი ++(MyArray x) //გადატვირთვაერთიანიოპერატორი ++

MyArray temp=new MyArray(x.length);

for (int i=0;i

temp[i]=++x.a[i]; // სცადეtemp.a[i]=++x.a[i]

//ინდექსატორი, თუ მასივი სცილდება ფარგლებს, გამონაკლისი გენერირებულია!

საჯარო ამაში

მიიღეთ (თუ (i>=0 && i

დააყენეთ ( თუ (i>=0 && i

საჯარო void Print (სტრიქონის სახელი)

Console.WriteLine(name+”:”);

for (int i=0;i

Console.WriteLine(“\t”+a[i]);

Console.WriteLine();

საჯარო void Enter()

//მარყუჟში - მასივის ელემენტების შეყვანა - თავად განახორციელეთ!

//class data – თავად მასივი და მისი განზომილება

MyArray a1=new MyArray(5,2,-1,1,-2);

a1.Print(„პირველი მასივი“);

1++; //ახლა შეგიძლიათ გამოიყენოთ ++ ოპერაცია კლასის მაგალითზე

a1.Print(„++ ოპერაციის გამოყენება მასივის ყველა ელემენტისთვის“);

MyArray a2=new MyArray(5);

a2.Print(„მეორე მასივი“);

2++;

a2.Print(„++ ოპერაციის გამოყენება მასივის ყველა ელემენტისთვის“);

დაჭერა (გამონაკლისი ე)

(Console.WriteLine(e.Message);)

ბევრი პროგრამირების ენა იყენებს ოპერატორებს: მინიმუმ, დავალებებს (=, := ან მსგავსი) და არითმეტიკული ოპერატორები (+, -, * და /). უმეტეს სტატიკურად აკრეფილ ენებში, ეს ოპერატორები დაკავშირებულია ტიპებთან. მაგალითად, ჯავაში + ოპერატორთან დამატება შესაძლებელია მხოლოდ მთელი რიცხვებისთვის, მცურავი წერტილის ნომრებისთვის და სტრიქონებისთვის. თუ ჩვენ განვსაზღვრავთ საკუთარ კლასებს მათემატიკური ობიექტებისთვის, როგორიცაა მატრიცები, ჩვენ შეგვიძლია განვახორციელოთ მათი დამატების მეთოდი, მაგრამ ჩვენ შეგვიძლია ვუწოდოთ მას მხოლოდ ასე: a = b.add(c) .

C++-ში ასეთი შეზღუდვა არ არსებობს - ჩვენ შეგვიძლია გადატვირთოთ თითქმის ნებისმიერი ცნობილი ოპერატორი. შესაძლებლობები უსასრულოა: თქვენ შეგიძლიათ აირჩიოთ ოპერანდების ტიპების ნებისმიერი კომბინაცია, ერთადერთი შეზღუდვა ის არის, რომ მინიმუმ ერთი ოპერანდი უნდა იყოს წარმოდგენილი. საბაჟო ტიპი. ანუ, განსაზღვრეთ ახალი ოპერატორი ჩაშენებულ ტიპებზე ან გადაწერეთ არსებული აკრძალულია.

როდის უნდა გადატვირთოთ ოპერატორები?

დაიმახსოვრეთ მთავარი: გადატვირთეთ ოპერატორები, თუ და მხოლოდ მაშინ, თუ ეს აზრი აქვს. ანუ თუ გადატვირთვის მნიშვნელობა აშკარაა და არ შეიცავს ფარულ სიურპრიზებს. გადატვირთული ოპერატორები უნდა მოიქცნენ ისევე, როგორც მათი საბაზისო ვერსიები. ბუნებრივია, გამონაკლისები დასაშვებია, მაგრამ მხოლოდ იმ შემთხვევებში, როდესაც მათ ახლავს მკაფიო განმარტებები. კარგი მაგალითია ოპერატორები<< и >> iostream სტანდარტული ბიბლიოთეკა, რომელიც აშკარად არ იქცევა ნორმალური ოპერატორების მსგავსად.

აქ მოცემულია ოპერატორის გადატვირთვის კარგი და ცუდი მაგალითები. ზემოთ მოყვანილი მატრიცის დამატება საილუსტრაციო შემთხვევაა. აქ დამატების ოპერატორის გადატვირთვა ინტუიციურია და სწორად განხორციელების შემთხვევაში არ საჭიროებს ახსნას:

მატრიცა a, b; მატრიცა c = a + b;

ცუდი დამატების ოპერატორის გადატვირთვის მაგალითი იქნება თამაშში ორი მოთამაშის ობიექტის დამატება. რას გულისხმობდა კლასის შემქმნელი? რა იქნება შედეგი? ჩვენ არ ვიცით, რას აკეთებს ოპერაცია და ამიტომ ამ ოპერატორის გამოყენება საშიშია.

როგორ გადავტვირთოთ ოპერატორები?

ოპერატორის გადატვირთვა მსგავსია სპეციალური სახელებით გადატვირთვის ფუნქციების. სინამდვილეში, როდესაც შემდგენელი ხედავს გამონათქვამს, რომელიც შეიცავს ოპერატორს და მომხმარებლის მიერ განსაზღვრულ ტიპს, ის ცვლის გამოხატვას გადატვირთული ოპერატორის შესაბამისი ფუნქციის გამოძახებით. მათი უმეტესი სახელები იწყება საკვანძო სიტყვით ოპერატორი, რასაც მოჰყვება შესაბამისი ოპერატორის აღნიშვნა. როდესაც აღნიშვნა არ შედგება სპეციალური სიმბოლოებისგან, მაგალითად, ტიპის კონვერტაციის ან მეხსიერების მართვის ოპერატორის შემთხვევაში (ახალი, წაშლა და ა.შ.), სიტყვა ოპერატორი და ოპერატორის აღნიშვნა უნდა იყოს გამოყოფილი ინტერვალით (ოპერატორი ახალი) წინააღმდეგ შემთხვევაში, სივრცე შეიძლება იგნორირებული იყოს (ოპერატორი+).

ოპერატორების უმეტესობის გადატვირთვა შესაძლებელია კლასის მეთოდებით ან მარტივი ფუნქციებით, მაგრამ არის რამდენიმე გამონაკლისი. როდესაც გადატვირთული ოპერატორი არის კლასის მეთოდი, პირველი ოპერანდის ტიპი უნდა იყოს ეს კლასი (ყოველთვის *this), ხოლო მეორე უნდა გამოცხადდეს პარამეტრების სიაში. გარდა ამისა, მეთოდის განცხადებები არ არის სტატიკური, გარდა მეხსიერების მართვის განცხადებებისა.

როდესაც თქვენ გადატვირთავთ ოპერატორს კლასის მეთოდში, ის იძენს წვდომას კლასის პირად ველებზე, მაგრამ პირველი არგუმენტის ფარული კონვერტაცია მიუწვდომელია. ამიტომ, ორობითი ფუნქციები ჩვეულებრივ გადატვირთულია როგორც თავისუფალი ფუნქციები. მაგალითი:

კლასი რაციონალური ( საჯარო: //კონსტრუქტორი შეიძლება გამოყენებულ იქნას int-დან იმპლიციტური კონვერტაციისთვის: Rational(int მრიცხველი, int მნიშვნელი = 1); რაციონალური ოპერატორი+(Rational const& rhs) const; ); int main() ( რაციონალური a, b, c; int i; a = b + c; //ok, არ არის საჭირო კონვერტაცია a = b + i; //ok, მეორე არგუმენტის იმპლიციტური კონვერტაცია a = i + c; //შეცდომა: პირველი არგუმენტი არ შეიძლება ირიბად გარდაიქმნას)

როდესაც ერთიანი ოპერატორები გადატვირთულია როგორც უფასო ფუნქციები, მათთვის ხელმისაწვდომია ფარული არგუმენტის კონვერტაცია, მაგრამ ეს ჩვეულებრივ არ გამოიყენება. მეორეს მხრივ, ეს თვისება აუცილებელია ბინარული ოპერატორებისთვის. ამიტომ, მთავარი რჩევა იქნება შემდეგი:

განახორციელეთ ერთიანი ოპერატორები და ორობითი ოპერატორები, როგორიცაა " X=” კლასის მეთოდების სახით, ხოლო სხვა ორობითი ოპერატორები – თავისუფალი ფუნქციების სახით.

რომელი ოპერატორების გადატვირთვა შეიძლება?

ჩვენ შეგვიძლია გადატვირთოთ თითქმის ნებისმიერი C++ ოპერატორი, შემდეგი გამონაკლისებისა და შეზღუდვების გათვალისწინებით:

  • თქვენ არ შეგიძლიათ განსაზღვროთ ახალი ოპერატორი, როგორიცაა ოპერატორი**.
  • შემდეგი ოპერატორების გადატვირთვა შეუძლებელია:
    1. ?: (სამიანი ოპერატორი);
    2. :: (წვდომა წყობილ სახელებზე);
    3. . (ველებზე წვდომა);
    4. .* (ველებზე წვდომა მაჩვენებლით);
    5. sizeof, typeid და cast ოპერატორები.
  • შემდეგი ოპერატორების გადატვირთვა შესაძლებელია მხოლოდ მეთოდების სახით:
    1. = (დავალება);
    2. -> (ველებზე წვდომა მაჩვენებლით);
    3. () (ფუნქციის გამოძახება);
    4. (წვდომა ინდექსით);
    5. ->* (pointer-to-field-ზე წვდომა მაჩვენებლით);
    6. კონვერტაციის და მეხსიერების მართვის ოპერატორები.
  • ოპერანდების რაოდენობა, შესრულების ბრძანება და ოპერატორების ასოციაციურობა განისაზღვრება სტანდარტული ვერსიით.
  • მინიმუმ ერთი ოპერანდი უნდა იყოს მომხმარებლის ტიპი. Typedef არ ითვლება.

შემდეგ ნაწილში წარმოდგენილი იქნება C++ ოპერატორის გადატვირთვა, ჯგუფურად და ინდივიდუალურად. თითოეულ მონაკვეთს ახასიათებს სემანტიკა, ე.ი. მოსალოდნელი ქცევა. გარდა ამისა, ნაჩვენები იქნება ტიპიური გზებიოპერატორების დეკლარაციები და განხორციელება.

C++ მხარს უჭერს ოპერატორის გადატვირთვას. რამდენიმე გამონაკლისის გარდა, C++ ოპერატორების უმეტესობა შეიძლება იყოს გადატვირთული, რაც იწვევს მათ განსაკუთრებულ მნიშვნელობას გარკვეულ კლასებთან მიმართებაში. მაგალითად, კლასმა, რომელიც განსაზღვრავს დაკავშირებულ სიას, შეიძლება გამოიყენოს + ოპერატორი ობიექტის სიაში დასამატებლად. სხვა კლასმა შეიძლება გამოიყენოს + ოპერატორი სრულიად განსხვავებული გზით. როდესაც ოპერატორი გადატვირთულია, არც ერთი მისი ორიგინალური მნიშვნელობა არ არის მნიშვნელოვანი. უბრალოდ, ახალი ოპერატორი განისაზღვრება ობიექტების გარკვეული კლასისთვის. ამიტომ, + ოპერატორის გადატვირთვა დაკავშირებული სიის დასამუშავებლად არ ცვლის მის ქცევას მთელ რიცხვებთან მიმართებაში.

ოპერატორის ფუნქციები, როგორც წესი, იქნება იმ კლასის წევრები ან მეგობრები, რისთვისაც ისინი გამოიყენება. მიუხედავად იმისა, რომ ბევრი მსგავსებაა, არსებობს გარკვეული განსხვავებები წევრი ოპერატორის ფუნქციების და მეგობარი ოპერატორის ფუნქციების გადატვირთვის გზებს შორის. ამ განყოფილებაში ჩვენ განვიხილავთ მხოლოდ წევრის ფუნქციების გადატვირთვას. ამ თავში მოგვიანებით ჩვენ გაჩვენებთ, თუ როგორ არის გადატვირთული ოპერატორის მეგობრების ფუნქციები.

ოპერატორის გადატვირთვის მიზნით, თქვენ უნდა განსაზღვროთ რას ნიშნავს ოპერატორი იმ კლასთან მიმართებაში, რომელზედაც ის გამოიყენება. ამისათვის განისაზღვრება ოპერატორის ფუნქცია, რომელიც განსაზღვრავს ოპერატორის მოქმედებას. ოპერატორის ფუნქციის დაწერის ზოგადი ფორმა იმ შემთხვევისთვის, როდესაც ის არის კლასის წევრი, აქვს ფორმა:

აკრიფეთ class_name::operator#(არგუმენტის_სიტი)
{
// კლასთან მიმართებაში განსაზღვრული მოქმედებები
}

აქ გადატვირთული ოპერატორი ჩანაცვლებულია # სიმბოლოთი და ტიპი განსაზღვრავს ოპერატორის მიერ დაბრუნებული მნიშვნელობების ტიპს. გადატვირთული ოპერატორის გამოყენების გასაადვილებლად
რთულ გამონათქვამებში, დაბრუნების მნიშვნელობა ხშირად ირჩევა ისეთივე ტიპის, როგორც კლასი, რომლისთვისაც ოპერატორი გადატვირთულია. არგუმენტების სიის ბუნება განისაზღვრება რამდენიმე ფაქტორით, როგორც ქვემოთ იქნება ნაჩვენები.

იმის სანახავად, თუ როგორ მუშაობს ოპერატორის გადატვირთვა, დავიწყოთ მარტივი მაგალითი. ის ქმნის კლასს three_d, რომელიც შეიცავს ობიექტის კოორდინატებს სამგანზომილებიან სივრცეში. შემდეგი პროგრამა გადატვირთავს + და = ოპერატორებს სამი_დ კლასისთვის:

#შეიცავს
კლასი მესამე_დ(

საჯარო:
სამი_დ ოპერატორი+(სამი_დ t);
სამი_დ ოპერატორი=(სამი_დ t);
void show();

};
// გადატვირთვა +
სამი_დ სამი_დ::ოპერატორი+(სამი_დ ტ)
{
სამი_დ ტემპერატურა;
ტემპ.x = x+t.x;
temp.y = y+t.y;
temp.z = z+t.z;
დაბრუნების ტემპერატურა;
}
// გადატვირთვა =
სამი_დ სამი_დ::ოპერატორი=(სამი_დ ტ)
{
x = t.x;
y = t.y;
z = t.z;
დაბრუნება *ეს;
}
// გამომავალი კოორდინატები X, Y, Z
void three_d::show()
{
კოუტ<< x << ", ";
კოუტ<< у << ", ";
კოუტ<< z << "\n";
}
// კოორდინატების მინიჭება

{
x = mx;
y = ჩემი;
z = mz;
}
int main()
{
სამი_დ a, b, c;
ა.მინიშნება(1, 2, 3);
ბ.დავალება(10, 10, 10);
ა.ჩვენება();
ბ.ჩვენება();
c = a+b; // a და b-ის დამატება
c.show();

c.show();

c.show();
ბ.ჩვენება();
დაბრუნება 0;
}

ეს პროგრამა აჩვენებს შემდეგ მონაცემებს:

1, 2, 3
10, 10, 10
11, 12, 13
22, 24, 26
1, 2, 3
1, 2, 3

თუ ყურადღებით დააკვირდებით ამ პროგრამას, შეიძლება გასაკვირი იყოს, რომ ორივე ოპერატორის ფუნქციას აქვს მხოლოდ ერთი პარამეტრი, მიუხედავად იმისა, რომ ისინი გადატვირთავს ორობით ოპერატორს. ეს იმიტომ ხდება, რომ როდესაც თქვენ გადატვირთავთ ორობით ოპერატორს წევრი ფუნქციის გამოყენებით, მას ცალსახად გადაეცემა მხოლოდ ერთი არგუმენტი. მეორე არგუმენტი არის ეს მაჩვენებელი, რომელიც მას გადაეცემა ირიბად. დიახ, რიგში

Temp.x = x + t.x;

X შეესაბამება ამ->x-ს, სადაც x ასოცირდება ობიექტთან, რომელიც იძახებს ოპერატორის ფუნქციას. ყველა შემთხვევაში, ოპერატორის ფუნქციის გამოძახება არის ოპერატორის ნიშნის მარცხნივ მდებარე ობიექტი. ოპერაციული ნიშნის მარჯვნივ მდებარე ობიექტი გადაეცემა ფუნქციას.

ერთიანი ოპერაციის გადატვირთვისას ოპერატორის ფუნქციას არ აქვს პარამეტრები, ხოლო ორობითი ოპერაციის გადატვირთვისას ოპერატორის ფუნქციას აქვს ერთი პარამეტრი. (არ შეგიძლიათ გადატვირთოთ ტრიადული ოპერატორი?:.) ყველა შემთხვევაში, ობიექტი, რომელიც იწვევს ოპერატორის ფუნქციას, გადაეცემა იმპლიციტურად ამ მაჩვენებლის გამოყენებით.

იმის გასაგებად, თუ როგორ მუშაობს ოპერატორის გადატვირთვა, მოდით ყურადღებით გავაანალიზოთ, როგორ მუშაობს წინა პროგრამა, დაწყებული გადატვირთული + ოპერატორით. როდესაც სამი_d ტიპის ორი ობიექტი ექვემდებარება + ოპერატორს, ემატება მათი შესაბამისი კოორდინატების მნიშვნელობები, როგორც ეს ნაჩვენებია ამ კლასთან ასოცირებულ ოპერატორ +() ფუნქციაში. ამასთან, გაითვალისწინეთ, რომ ფუნქცია არ ცვლის ოპერანდების მნიშვნელობებს. ამის ნაცვლად, ის აბრუნებს სამი_d ტიპის ობიექტს, რომელიც შეიცავს ოპერაციის შედეგს. იმის გასაგებად, თუ რატომ არ ცვლის + ოპერატორი ობიექტების შიგთავსს, შეგიძლიათ წარმოიდგინოთ სტანდარტული არითმეტიკული ოპერატორი +, რომელიც გამოიყენება შემდეგნაირად: 10 + 12. ამ ოპერაციის შედეგია 22, მაგრამ არც 10 და არც 12 არ იცვლება. მიუხედავად იმისა, რომ არ არსებობს წესი, რომ გადატვირთულ ოპერატორს არ შეუძლია შეცვალოს მისი ოპერანდების მნიშვნელობები, ჩვეულებრივ აზრი აქვს მის დაცვას. ამ მაგალითს რომ დავუბრუნდეთ, არ არის სასურველი, რომ + ოპერატორმა შეცვალოს ოპერანდების შინაარსი.

დამატებითი ოპერატორის გადატვირთვის კიდევ ერთი მნიშვნელოვანი პუნქტი არის ის, რომ ის აბრუნებს სამი_d ტიპის ობიექტს. მიუხედავად იმისა, რომ ფუნქციას შეუძლია მიიღოს ნებისმიერი მოქმედი C++ ტიპი, როგორც მნიშვნელობა, ის ფაქტი, რომ ის აბრუნებს სამი_d ტიპის ობიექტს, საშუალებას აძლევს + ოპერატორის გამოყენებას უფრო რთულ გამონათქვამებში, როგორიცაა a+b+c. აქ a+b აწარმოებს სამი_d ტიპის შედეგს. ეს მნიშვნელობა შემდეგ ემატება c. თუ a+b ჯამის მნიშვნელობა სხვა ტიპის მნიშვნელობა იყო, მაშინ ვერ დავამატებდით c-ს.

+ ოპერატორისგან განსხვავებით, მინიჭების ოპერატორი ცვლის თავის არგუმენტებს. (ეს, სხვა საკითხებთან ერთად, არის მინიჭების მნიშვნელობა.) ვინაიდან ოპერატორი=() ფუნქცია იძახება ტოლობის ნიშნის მარცხნივ მდებარე ობიექტის მიერ, სწორედ ეს ობიექტია მოდიფიცირებული.
დავალების შესრულებისას. თუმცა, მინიჭების ოპერატორმაც კი უნდა დააბრუნოს მნიშვნელობა, რადგან C++ და C-ში მინიჭების ოპერატორი აწარმოებს მნიშვნელობას ტოლობის მარჯვენა მხარეს. ასე რომ, შემდეგი ფორმის გამოხატვის მიზნით

A = b = c = d;

კანონიერი იყო ოპერატორს=()-ის მოთხოვნა ამ მაჩვენებლის მიერ მითითებული ობიექტის დასაბრუნებლად, რომელიც იქნება მინიჭების ოპერატორის მარცხენა მხარეს არსებული ობიექტი. თუ ამას აკეთებთ ამ გზით, შეგიძლიათ შეასრულოთ მრავალი დავალება.

შესაძლებელია ერთიანი ოპერატორების გადატვირთვა, როგორიცაა ++ ან --. როგორც უკვე აღვნიშნეთ, როდესაც თქვენ გადატვირთავთ უნიალურ ოპერატორს წევრი ფუნქციის გამოყენებით, წევრის ფუნქციას არ აქვს არგუმენტები. სამაგიეროდ, ოპერაცია შესრულებულია ობიექტზე, რომელიც იწვევს ოპერატორის ფუნქციას ამ მაჩვენებლის იმპლიციურად გადაცემით. მაგალითად, ქვემოთ მოცემულია წინა პროგრამის გაფართოებული ვერსია, რომელიც განსაზღვრავს ზრდის ოპერატორს სამი_d ტიპის ობიექტისთვის:

#შეიცავს
კლასი მესამე_დ(
int x, y, z; // 3D კოორდინატები
საჯარო:
სამი_დ ოპერატორი+(სამი_დ op2); // op1 იგულისხმება
სამი_დ ოპერატორი=(სამი_დ op2); // op1 იგულისხმება
სამი_დ ოპერატორი ++(); // op1 ასევე იგულისხმება
void show();
void assign(int mx, int my, int mz);
};
// გადატვირთვა +
three_d three_d::ოპერატორი+(სამი_დ op2)
{
სამი_დ ტემპერატურა;
temp.x = x+op2.x; // მთელი რიცხვის დამატება
temp.у = y+op2.y; // და ამ შემთხვევაში + ინახავს
temp.z = z+op2.z; // საწყისი მნიშვნელობა
დაბრუნების ტემპერატურა;
}
// გადატვირთვა =
three_d three_d::operator=(სამი_დ op2)
{
x = op2.x; // მთელი რიცხვის მინიჭება
y = op2.y; // და ამ შემთხვევაში = ინახავს
z = op2.z; // საწყისი მნიშვნელობა
დაბრუნება *ეს;
}
// ერთიანი ოპერატორის გადატვირთვა
three_d three_d::operator++()
{
x++;
y++;
z++;
დაბრუნება *ეს;
}
// X, Y, Z კოორდინატების ჩვენება
void three_d::show()
{
კოუტ<< x << ", ";
კოუტ<< у << ", ";
კოუტ<< z << "\n";
}
// კოორდინატების მინიჭება
void three_d:: მინიჭება (int mx, int my, int mz)
{
x = mx;
y = ჩემი;
z = mz;
}
int main()
{
სამი_დ a, b, c;
ა.მინიშნება(1, 2, 3);
ბ.დავალება(10, 10, 10);
ა.ჩვენება();
ბ.ჩვენება();
c = a+b; // a და b-ის დამატება
c.show();
c = a+b+c; // a, b და c-ის დამატება
c.show();
c = b = a; // მრავალჯერადი დავალების დემონსტრირება
c.show();
ბ.ჩვენება();
++c; // გაზრდა საწყისი
c.show();
დაბრუნება 0;
}

C++-ის ადრეულ ვერსიებში შეუძლებელი იყო იმის დადგენა, ოპერანდს წინ უძღვის თუ მოჰყვება გადატვირთული ++ ან -- ოპერატორი. მაგალითად, ობიექტისთვის O, შემდეგი ორი ინსტრუქცია იდენტური იყო:

O++;
++O;

თუმცა, C++-ის უფრო გვიანდელი ვერსიები საშუალებას იძლევა განასხვავონ პრეფიქსი და პოსტფიქსი ინკრემენტის და შემცირების ოპერატორების ფორმებს შორის. ამისათვის პროგრამამ უნდა განსაზღვროს ოპერატორი ++() ფუნქციის ორი ვერსია. ერთი მათგანი უნდა იყოს იგივე, რაც ნაჩვენებია წინა პროგრამაში. მეორე გამოცხადებულია შემდეგნაირად:

Loc ოპერატორი ++ (int x);

თუ ++ წინ უსწრებს ოპერანდს, გამოიძახება ოპერატორი ++(). თუ ++ მიჰყვება ოპერანდს, მაშინ გამოიძახება ფუნქციის ოპერატორი ++(int x), სადაც x იღებს მნიშვნელობას 0.

გადატვირთული ოპერატორის ეფექტი კლასზე, რომლისთვისაც ის არის განსაზღვრული, არანაირად არ უნდა შეესაბამებოდეს ამ ოპერატორის ეფექტს C++ ჩაშენებულ ტიპებზე. მაგალითად, ოპერატორები<< и >> როგორც გამოიყენება cout-სა და cin-ზე, ნაკლებად აქვს საერთო მათ გავლენას მთელი რიცხვის ტიპის ცვლადებზე. თუმცა, იმისათვის, რომ კოდი უფრო წაკითხული და კარგად სტრუქტურირებული გახდეს, სასურველია, რომ გადატვირთული ოპერატორები შეესაბამებოდეს ორიგინალური ოპერატორების განზრახვას, სადაც ეს შესაძლებელია. მაგალითად, + ოპერატორი სამი_d კლასისთვის კონცეპტუალურად მსგავსია + ოპერატორის მთელი ტიპის ცვლადებისთვის. მაგალითად, მცირე სარგებლიანობა შეიძლება მოსალოდნელი იყოს ასეთი + ოპერატორისგან, რომლის ეფექტიც არის
შესაბამისი კლასი დაემსგავსება ||-ის მოქმედებას. მიუხედავად იმისა, რომ თქვენ შეგიძლიათ გადატვირთულ ოპერატორს მიანიჭოთ ნებისმიერი მნიშვნელობა, რაც არჩეული გაქვთ, გამოყენების სიცხადისთვის სასურველია, რომ მისი ახალი მნიშვნელობა დაკავშირებული იყოს თავდაპირველ მნიშვნელობასთან.

არსებობს გარკვეული შეზღუდვები ოპერატორის გადატვირთვაზე. პირველი, თქვენ არ შეგიძლიათ შეცვალოთ ოპერატორის უპირატესობა. მეორეც, თქვენ არ შეგიძლიათ შეცვალოთ ოპერატორის ოპერანდების რაოდენობა. დაბოლოს, მინიჭების ოპერატორის გარდა, გადატვირთული ოპერატორები მემკვიდრეობით მიიღება ნებისმიერი წარმოებული კლასის მიერ. თითოეულმა კლასმა მკაფიოდ უნდა განსაზღვროს საკუთარი გადატვირთული = ოპერატორი, თუ ეს საჭიროა რაიმე მიზნისთვის. რა თქმა უნდა, მიღებულ კლასებს შეუძლიათ გადატვირთონ ნებისმიერი ოპერატორი, მათ შორის ის, რომელიც გადატვირთული იყო საბაზისო კლასის მიერ. შემდეგი ოპერატორების გადატვირთვა შეუძლებელია:
. :: * ?



რაიმე შეკითხვა?

შეატყობინეთ შეცდომას

ტექსტი, რომელიც გაეგზავნება ჩვენს რედაქტორებს: