سؤال

إذا كان ما يلي من Faq Lite C ++ صحيحًا: "اسم وظيفة يتحلل إلى مؤشر إلى الوظيفة" (كاسم صفيف يتحلل إلى مؤشر إلى عنصره الأول) ؛ لماذا يتعين علينا تضمين ampersand؟

typedef  int (Fred::*FredMemFn)(char x, float y);
FredMemFn p = &Fred::f;

وليس فقط:

typedef  int (Fred::*FredMemFn)(char x, float y);
FredMemFn p = Fred::f;

في الحالة الثانية ، يكون Fred :: F وظيفة ويمكن أن يتحلل إلى مؤشر إلى هذه الوظيفة.

آمل ألا يكون هذا السؤال بهذه الغباء.

هل كانت مفيدة؟

المحلول

الإجابة الأصلية:

لأن الوظيفة العضو ليست دالة وأن العضو الوظيفي ليس مؤمنًا للدالة. لذلك لا تنطبق قواعد التحلل.

أيضًا ، هناك نوع وظيفة في نوع C ++ ، ولكن ليس نوع الوظيفة الأعضاء. حتى تتمكن من استخدام وظيفة في الأماكن التي يتوقع فيها مؤشر إلى وظائف ، ولكن لا يمكنك استخدام وظيفة عضو لأنه لا يوجد شيء من هذا القبيل ، فقط المؤشر إلى العضو. F في مثالك هي وظيفة. من ناحية أخرى ، فريد :: f هو ... حسنا ، لا شيء.

أيضا ، أود أن أزعم أن "اسم الوظيفة يمكن أن يتحلل ...". لا ، لا يمكن للاسم أن يفعل أي شيء ، يمكن تحويل LVALUE من نوع الوظيفة ضمنيًا إلى مؤشر إلى وظائف ، وهذا هو تحويل الهوية فيما يتعلق بدقة التحميل الزائد

التحرير لتوضيح إجابتي:

كل تعبير في C ++ له نوع وقيمة. يمكن تحويل قيمة نوع واحد في بعض الأحيان إلى قيمة من نوع آخر. يتم تصنيف هذه التحويلات بحيث تجعل تحويل واحد أفضل بشكل أساسي لتحل الوظيفة الزائدة.

يسمى أحد أنواع التحويلات تحويل lvalue إلى rvalue. عندما يظهر LVALUE في سياق يلزم RVALUE هذا التحويل. عادةً ما لا يفعل هذا النوع من التحويل ، على سبيل المثال:

int i = 4, j = 5;
i = j;

على السطر الثاني J هو lvalue ، ولكن هناك حاجة إلى rvalue هنا ، لذلك يتم تحويل J إلى rvalue. لكن هذا ليس تحويلًا يمكن ملاحظته ، أليس كذلك؟ ولكن هناك حالات يمكن ملاحظة تحويل LVALUE إلى RVALUE. إنه، يمكن تحويل LVALUE من مجموعة من n t إلى rvalue من النوع T* من قيمته هو عنوان العنصر الأول من المصفوفة و lvalue من نوع "وظيفة مع التوقيع s" rvalue من النوع "مؤشر للعمل مع التوقيع S" الذي تكون قيمتها هي عنوان الوظيفة

هذا يعني أنه عندما نقوم بتعيين وظيفة لمؤشر إلى الوظيفة ، يتم تحويل الدالة LVALUE ضمنيًا إلى عنوانه.

void f() {}
void (*p) () = f; //f is converted to rvalue

F هو تعبير وله نوع. نوع F هو void()

لا يوجد نوع من هذا النوع في C ++ مثل member-functionهناك مؤشرات إلى أعضاء ، ولكن ليس وظائف الأعضاء نفسها. أنا أتحدث بالطبع عن الوظائف غير المستقلة. تعمل الوظائف الثابتة بنفس الطريقة التي تعمل بها الوظائف العادية ، أي أنك لا تضطر إلى الكتابة &X::f, ، بدلاً من ذلك يمكنك الكتابة X::fلماذا ا؟ لأن x :: f لها وظيفة نوع ويتم التحويل المذكور. إذا كان F غير ثابت ، ومع ذلك ، X :: F من النوع ... ماذا؟ أوه نعم ، لا يحتوي على نوع وبالتالي ليس تعبيرًا وبالتالي ليس له قيمة وبالتالي لا يمكن تحويل هذه القيمة إلى أي شيء.

اقتباس من المعيار: 5.3.1 البند 3 لا يتم تشكيل مؤشر إلى العضو إلا عند استخدامه بشكل صريح ويتم استخدامه ومعامله هو معرف مؤهل غير محاط بين أقواس. [ملاحظة: هذا هو ، التعبير و (المعرف المؤهل) ، حيث يتم إرفاق المعرفة المؤهلة بين قوسين ، لا يشكل تعبيرًا عن نوع "مؤشر إلى العضو". لا لا يوجد معرف مؤهل ، لأنه لا يوجد تحويل ضمني من معرف مؤهل لوظيفة عضو غير مستقر إلى نوع "مؤشر إلى وظيفة العضو" كما هو الحال من lvalue من نوع الوظيفة إلى نوع "المؤشر إلى الوظيفة" (4.3 ). كما أنه ليس مؤشرًا غير مؤهل لعضو ، حتى في نطاق فئة المعالم غير المؤهلة.

أتمنى أن يكون هذا أكثر وضوحًا ...

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top