التعداد C ++ لم يتم التعرف عليه بشكل صحيح بواسطة برنامج التحويل البرمجي
-
22-08-2019 - |
سؤال
هل يمكن لأي شخص أن يشرح لماذا لا يتم تجميع الكود التالي (على G ++ (GCC) 3.2.3 20030502 (Red Hat Linux 3.2.3-49))؟
struct X {
public:
enum State { A, B, C };
X(State s) {}
};
int main()
{
X(X::A);
}
الرسالة التي أحصل عليها هي:
JJJ.CPP: في الوظيفة "int main ()":
JJJ.CPP: 10: "XX :: A" ليس عضوًا ثابتًا في "Struct X"
JJJ.CPP: 10: لا توجد وظيفة مطابقة للاتصال بـ "X :: X ()"
jjj.cpp: 1: المرشحون هم: x :: x (const x &)
jjj.cpp: 5: x :: x (x :: state) ``
هل هذا الرمز السيئ أم علة المترجم؟
مشكلة حلها نيل+كونراد. انظر التعليقات على إجابة نيل أدناه.
المحلول
X(X::A);
يُرى إعلان وظيفة ASA. إذا كنت تريد حقًا هذا الرمز ، فاستخدم:
(X)(X::A);
نصائح أخرى
لقد نسيت الاسم المتغير في تعريفك:
int main()
{
X my_x(X::A);
}
يربك الرمز الخاص بك المترجم لأنه لا يمكن أن يميز هذا عن إعلان الوظيفة (العودة X
ويمر X::A
كحجة). عندما تكون في شك ، يقوم برنامج التحويل البرمجي C ++ دائمًا بإزالة الغموض لصالح الإعلان.
الحل هو تقديم قوسين زائدين حول X
نظرًا لأن المترجم يمنع الأقواس حول الأنواع (على عكس مكالمات البناء وما إلى ذلك):
(X(X::A));
فقط لجعله واضحا ما يحدث. انظر إلى هذا المثال
int main() {
float a = 0;
{
int(a); // no-op?
a = 1;
}
cout << a;
}
ماذا ستخرج؟ حسنًا ، سوف يخرج 0
. ال int(a)
يمكن تحليلها أعلاه بطريقتين مختلفتين:
- يلقي إلى int وتجاهل النتيجة
- إعلان متغير يسمى
a
. لكن تجاهل الأقواس حول المعرف.
المترجم ، عندما يظهر مثل هذا الموقف حيث يتم استخدام فريق عمل على غرار الوظيفة في بيان ويبدو أنه إعلان أيضًا ، سيأخذه دائمًا كإعلان. عندما لا يمكن أن يكون إعلانًا (سوف ينظر المترجم إلى الخط بأكمله لتحديد ذلك) ، سيتم اعتباره تعبيرًا. وبالتالي نحن نخصص للداخلية a
أعلاه ، ترك الخارجي a
في الصفر.
الآن ، قضيتك هي بالضبط. أنت تحاول (عن طريق الخطأ) إعلان معرف يسمى A
ضمن فصل يسمى X
:
X (X::A); // parsed as X X::A;
ثم يمتد المترجم إلى أنين حول مُنشئ افتراضي غير معلن ، لأن الثابت ، كما يفترض أنه ، تم إنشاؤه الافتراضي. ولكن حتى لو كان لديك مُنشئ افتراضي لـ X ، فلا يزال بالطبع خطأ لأنه لا A
هو عضو ثابت في X ، ولا يمكن تعريف/إعلان ثابت من X في نطاق الكتلة.
يمكنك أن تجعله ليس تبدو وكأنها إعلان عن طريق القيام بعدة أشياء. أولاً ، يمكنك Paren التعبير كله ، مما يجعله لا يبدو وكأنه إعلان بعد الآن. أو فقط Paren النوع الذي يلقي. تم ذكر كل من هذه الأزياء في إجابات أخرى:
(X(X::A)); (X)(X::A)
هناك غموض مشابه ، ولكنه متميز عندما تحاول إعلان كائن بالفعل. انظر إلى هذا المثال:
int main() {
float a = 0;
int b(int(a)); // object or function?
}
لان int(a)
يمكن أن يكون كل من إعلان معلمة تسمى a
والتحويل الصريح (المصبوب) للمتغير العائم إلى INT ، يقرر المترجم مرة أخرى أن هذا إعلان. وبالتالي ، فإننا نعلن عن وظيفة تسمى b
, ، والتي تأخذ حجة عدد صحيح ويعيد عدد صحيح. هناك العديد من الاحتمالات كيفية إزالة الغموض التي ، بناءً على الغموض أعلاه:
int b((int(a))); int b((int)a);
يجب أن تعلن كائن
X x(X::A);
خطأ في الكود الخاص بك.
أي من هذين الخطين يعملان بالنسبة لي:
X obj(X::A);
X obj2 = X(X::A);
كما يشير نيل بتروورث ، X(X::A)
يتم التعامل معها كإعلان وظيفة. إذا كنت تريد حقًا كائن مجهول ، (X)(X::A)
سوف بناء كائن X وحذفه على الفور.
يمكنك ، بالطبع ، أن تفعل شيئًا كهذا:
int main()
{
// code
{
X temp(X::A);
}
// more code
}
سيكون هذا أكثر قابلية للقراءة وله نفس التأثير.