سؤال

هنا هو فئة فو:

template <typename T>
struct foo
{
    foo()
    {
        t = nullptr;
    }

    foo(T* p, bool flag)
    {
        t = p;
    }
private:
    T* t;
};

هنا هو شريط الطبقة:

template <typename T>
struct bar: public foo<T>
{
    using foo<T>::foo<T>;
};

هل هو بناء الجملة الصحيح لمنشئات وراثة?إذا كنت تستخدم "باستخدام فو:: فو؛" ثم مترجم البصرية ج 2 2010 يموت.وذلك أساسا كيفية وراثة منشئات من الطبقات قالب في فك 2 2010?

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

المحلول

template <typename T>
struct bar: public foo<T>
{
    using foo<T>::foo<T>;
};

للسماح لهذا التحليل بشكل صحيح ، ستحتاج إلى إدراج template قبل foo<T>;, ، لإخبار المترجم بذلك foo هو أن ينظر إليه على أنه اسم قالب (لا يمكن النظر فيه foo<T> لتخبر نفسها ، منذ ذلك الحين T غير معروف).ولكن باستخدام ::template غير مسموح به في إعلان استخدام.الاسم أيضا لا يشير إلى جميع منشئي bar:بدلا من ذلك ، قد يشير إلى تخصص قالب دالة منشئ معين (T هي وسيطة القالب) لمثل هذا المنشئ على النحو التالي

template<typename T>
foo();

وبالإضافة إلى ذلك ، انها ليست صالحة لإعلان استخدام لاستخدام template-id (مثل foo<T>) كاسمها (الذي يمنعها في الواقع من الإشارة إلى تخصص قالب الوظيفة ، مع إضافة حظر تسمية تخصصات قالب وظيفة التحويل المذكورة أيضا) ، لذلك حتى إذا قمت بتصحيح مشكلة التحليل باستخدام ::template (إذا كان ذلك ممكنا) ، فستظل تخطئ في هذه المرحلة.

عندما تم تقديم المنشئات الموروثة ، تمت إضافة قواعد خاصة تسمح بالإشارة إلى المنشئ باستخدام قاعدة نحوية:إذا كان لديك معرف مؤهل (والذي يستخدم أساسا اسما مؤهلا ...::...) ، وآخر مؤهل قبل الجزء الأخير يسمي فئة معينة، ثم يمكنك الإشارة إلى منشئ(ق) من تلك الفئة بطريقتين إضافيتين:

  • إذا تم تسمية الفئة باستخدام معرف قالب (اسم النموذج foo<T>) والجزء الأخير يطابق اسم القالب (لذلك, foo<T>::foo أو TTP<T>::TTP مع TTP كونها معلمة قالب قالب).
  • إذا كان الجزء الأخير يطابق اسم الفئة (لذلك, foo::foo أو T::T, ، مع T كونها معلمة قالب).

هذه القواعد الإضافية اثنين نشطة فقط في إعلان استخدام.وكانوا بطبيعة الحال غير موجودين في 03 دولار كندي.القاعدة الأخرى التي كانت موجودة أيضا في 03 دولار كندي هي:إذا كان الجزء الأخير يسمي اسم الفئة المحقون ، فإن هذا الاسم المؤهل يشير أيضا إلى المنشئ:

  • foo::foo سوف تعمل لذلك.ولكن مع هذه القاعدة وحدها, T::T (أين T يدل على الطبقة foo) لن تعمل ، لأن foo لا يوجد لديه عضو يسمى T.

لذلك ، مع القواعد الخاصة المعمول بها ، يمكنك الكتابة

using foo<T>::foo;
using bar::foo::foo; // valid too

والثاني صالح أيضا: foo هو اسم الفئة المحقون الذي تم حقنه في الفئة الأساسية foo<T> ورثت إلى bar.نشير إلى هذا الاسم من خلال bar::foo, ، ثم أضف الجزء الأخير foo, ، الذي يشير إلى اسم الفئة حقن مرة أخرى ، للدلالة على منشئ(ق) من `فو.

أنت الآن تفهم لماذا يشير الاسم الأولي الذي جربته إلى تخصص قالب دالة المنشئ (إذا كان مسموحا به):لأن foo<T>::foo جزء من شأنه تسمية جميع الصانعين ، و <T> التي من شأنها أن تتبع ثم تصفية القالب وتمرير وسيطة النوع.

نصائح أخرى

إذا كان برنامج التحويل البرمجي الخاص بك لا يدعم استخدام المنشئات الموروثة حتى الآن ، ولكنه يدعم وحدات الماكرو المتنوعة ، والقوالب المتغيرة ومراجع rvalue ، و type_trait سهل الاستخدام ، فإليك حلاً مناسبًا حقًا: Genacodicetagpre

إذا لم يكن لديك is_constructible حتى الآن ، فستعمل الفكرة الأساسية بدونها ، لكن "المُنشئ الموروث" سيكون جشعًا للغاية.

لست بحاجة إلى معلمة النموذج الثانية ؛ Genacodicetagpre

يجب أن تفعل

تحرير أتراجع عن أن هذا يعمل على g ++ - 4.4.1 ، ولكن يجب أن تكون هذه هي الصيغة الصحيحة عندما تصبح الميزة متاحة

لقد قامت الإجابات الأخرى بالفعل بعمل جيد في شرح كيفية عمل المُنشئات الوراثية في C ++ 0x.ومع ذلك ، حتى كتابة هذه السطور ، لم يقم أي مترجم بتنفيذ مجموعة ميزات C ++ 0x بالكامل.لسوء الحظ ، هذا يعني أن VC ++ 2010 لا يدعم استخدام المنشئات الموروثة حتى الآن.

لم يتم نشر معيار C ++ 0x.سيتم الانتهاء من المسودة النهائية للمعيار في وقت ما فيآذار (مارس) ، ولكن الأمر سيستغرق بضعة أشهر أخرى حتى يتم نشره بواسطة ISO.خلال ذلك الوقت ، يقوم كتّاب المترجمين بطرح ميزات بحيث تكون متوافقة مع C ++ 0x بقدر الإمكان عند الانتهاء من المعيار.

أعتقد أن أحدث إصدار من GCC يدعم وراثة المُنشئين ، لذلك إذا كان عليك تجربته الآن ، فيمكنك استخدامه.بالطبع ، دعم C ++ 0x تجريبي وقابل للتغيير عند اكتشاف الأخطاء ، وما إلى ذلك.

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