بالمعرفة التي لدينا الآن، قد يكون تحديث متغير بمساعدة دالة أمرًا مرهقًا بعض الشيء. يُعامل كل وسيط تمرّره إلى دالة كما لو كان نسخة، فلا يغيّر القيمة الأصلية. وبحسب حجم النوع الذي تستخدمه، قد يكون لهذا عواقب وخيمة على أداء الكود.
int adjust_salary(int base, int kids) {
return base + kids * 500;
}
int now_a_mother_of_twins{2500};
adjust_salary(now_a_mother_of_twins, 2);
// now_a_mother_of_twins is still 2500
now_a_mother_of_twins = adjust_salary(now_a_mother_of_twins, 2);
// now_a_mother_of_twins is now 3500
يمكن النظر إلى References على أنها أسماء مستعارة، إذ إن التغييرات التي تُجرى عليها تنعكس على المتغير الأصلي.
وتستخدم References علامة العطف (&) في تعريف النوع.
int balance{1000};
int& budget{balance};
int pro_computer_wheels{699};
budget -= pro_computer_wheels;
// budget is now 301;
// balance is also 301;
لا يمكن إعادة ربط reference، أي تغيير الجهة التي يرتبط بها.
ولا يمكن وجود reference غير مُهيَّأ.
يجب تهيئة References بمتغير موجود.
int main_acc{1'000'000};
int side_acc{-20};
int& savings{main_acc};
// => main_acc and savings are 1'000'000
// try to reseat savings to use main account
savings = side_acc;
// savings and main_acc are now -20
// as this uses the **value** of side_acc
savings += 20;
// savings and main_acc are now 0, side_acc is still -20
int& future_budget;
// => compiler error, reference must be bound!
voidبفضل قوة references، قد لا تحتاج إلى إرجاع قيمة من الدالة على الإطلاق.
وفي هذه الحالة يُستخدم void كنوع الإرجاع.
void increase_power(int& level) {
level += 500;
}
int goku{8700};
increase_power(goku);
// goku's power level?
// It's over 9000!
توجد مدرسة محلية قريبة منك لديها جمعية طلاب نشطة للغاية. تُدار جمعية الطلاب بواسطة رئيس، وكل سنتين تُجرى انتخابات لانتخاب رئيس جديد.
في انتخابات هذا العام، تقرر أن هناك حاجة إلى نظام رقمي جديد لعدّ الأصوات. تحتاج المدرسة إلى مساعدتك في بناء هذا النظام الجديد.
ElectionResult
سيحتاج النظام الجديد إلى وسيلة للحصول على عدد الأصوات من عدّاد.
تم إنشاء بنية نتيجة الانتخابات مسبقًا، وهي معرّفة كما يلي:
struct ElectionResult {
// Name of the candidate
std::string name{};
// Number of votes the candidate has
int votes{};
};
بما أن جميع الأعضاء في struct عامة، لا تحتاج إلى كتابة constructor لتهيئة كائن ElectionResult. يمكنك استخدام initializer list بدلاً من ذلك:
ElectionResult hamilton{"Alex", 1804};
// => the hamilton object was initialized with the name "Alex" and 1804 votes.
أنشئ دالة vote_count تأخذ مرجعًا إلى ElectionResult كوسيط وتُرجع عدد الأصوات في ElectionResult.
vote_count(hamilton);
// => 1804
ElectionResult
حان وقت معالجة الأصوات أخيرًا! الآن تحتاج إلى وسيلة لزيادة الأصوات في ElectionResult.
أنشئ دالة void باسم increment_vote_count تأخذ مرجعًا إلى ElectionResult كوسيط وعددًا من الأصوات، وتزيد ElectionResult بذلك العدد من الأصوات.
ElectionResult burr{"Aaron " 1801};
increment_vote_count(burr, 3);
vote_count(burr);
// => 1804
سلّمت المدرسة أصواتها، وحان الآن وقت التحقق من النتائج لمعرفة الفائز.
أنشئ دالة determine_result تستقبل مرجعًا إلى العدّ النهائي وتُرجع مرجعًا إلى ElectionResult الخاص بالرئيس الجديد. يجب أن تغيّر أيضًا اسم الفائز بإضافة "President" في بدايته. يُعطى العدّ النهائي على شكل reference إلى std::vector<ElectionResult>، وهو متجه يحتوي على ElectionResults لجميع المرشحين المشاركين.
ElectionResult sanchez{"Pedro", 471};
ElectionResult wheatley{"Summer", 340};
std::vector<ElectionResult> final_count{sanchez, wheatley};
ElectionResult& winner = determine_result(final_count);
winner.name;
// => "President Pedro"
لتبسيط الأمور، يمكنك افتراض ما يلي:
vector على عنصر واحد على الأقل.سجّل في Exercism لتتعلّم وتتقن C++ عبر 19 مفهومًا100 تمرين، وإرشاد بشري حقيقي، وكل ذلك مجانًا.