ج 0 0س منشئ الموروثة في قوالب
-
29-10-2019 - |
سؤال
هنا هو فئة فو:
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 تجريبي وقابل للتغيير عند اكتشاف الأخطاء ، وما إلى ذلك.