سؤال

النظر في فصل مثل ذلك:

template < class T >
class MyClass
{
  private:
    static T staticObject;
    static T * staticPointerObject;
};
...
template < class T >
T MyClass<T>::staticObject; // <-- works
...
template < class T >
T * MyClass<T>::staticPointerObject = NULL; // <-- cannot find symbol staticPointerObject.

أواجه مشكلة في معرفة سبب عدم قدرتي على إنشاء كائن المؤشر هذا بنجاح.

تم تحديد الرمز أعلاه في الرأس ، والمشكلة التي ذكرتها هي خطأ في خطوة الارتباط ، لذلك لا يجد الرمز المحدد.

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

المحلول 4

لقد وجدت حلين. أيا منهما 100 ٪ ما كنت آمل.

  1. تهيئة مثيل محدد بشكل واضح ، على سبيل المثال

    int * MyClass<int>::staticPointerObject = NULL;

هذا ليس مقنناً خاصة عندما يكون لدي الكثير من الأنواع المختلفة.

  1. لف المؤشر داخل الفصل ، على سبيل المثال

    template < class T >   
    class MyClass   
    {   
      private:   
        struct PointerWrapper   
        {   
          T * pointer;   
          PointerWrapper( void )   
            : pointer( NULL )   
          { }   
        };   
        T staticObject;   
        PointerWrapper staticPointerObject;   
    };   
    ...   
    template < class T >   
    T MyClass<T>::staticObject; // <-- works fine.   
    ...   
    template < class T >   
    MyClass<T>::PointerWrapper MyClass<T>::staticPointerObject; // <-- works fine.

هذا القليل من المتاعب ، ولكن على الأقل قابل للاستخدام. لماذا يمكنني إنشاء كائن متغير ولكن ليس مؤشرًا لكائن متغير؟ إذا كان هناك أي شيء أعتقد أنه سيكون لدي المزيد من المشكلات في الاتجاه الآخر (يعرف المترجم في وقت مبكر كيف يبدو المؤشر ، ولكن ليس شكل كائني).

إذا كان لدى شخص ما إجابة أفضل ، فأنا أحب أن أراه!

نصائح أخرى

"لا يمكن العثور على رمز StaticPointerObject" - هذا يبدو وكأنه أ رابط رسالة خطأ. فعلا؟ (يجب تحديد تفاصيل مثل هذه في سؤالك).

إذا كان الأمر كذلك ، فمن المحتمل أن يحدث ذلك لأنك وضعت التعريف (التعريفات) لعضوتك الثابتة في التنفيذ ملف (ملف .cpp). لكي يعمل هذا بشكل صحيح ، يجب وضع التعريفات في ملف الرأس (ملف .h).

مرة أخرى ، يجب تحديد تفاصيل مثل هذه في سؤالك. بدونهم يتحول إلى مهرجان تخمين عشوائي.

أظن أن السبب في مثالك الأول هو ما يلي (من مستند C ++ STD 2003). لاحظ بشكل خاص الجملة الأخيرة - من مثالك ، يبدو أن هناك شيئًا "يتطلب وجود تعريف العضو".

14.7.1 مثيل ضمني [temp.inst] 1 ما لم يتم إنشاء تخصص قالب الفصل بشكل صريح (14.7.2) أو متخصصة بشكل صريح (14.7.3) ، يتم إنشاء تخصص قالب الطبقة ضمنيًا عند الإشارة إلى التخصص في سياق ذلك يتطلب نوع كائن محدد بالكامل أو عندما يؤثر اكتمال نوع الفصل على دلالات البرنامج. يؤدي الاستئصال الضمني لتخصص قالب الفصل إلى التثبيت الضمني للإعلانات ، ولكن ليس للتعريفات أو الوسيطات الافتراضية ، وظائف الأعضاء في الفصل ، وفئات الأعضاء ، وأعضاء البيانات الثابتة وقوالب الأعضاء ؛ ويسبب التثبيت الضمني لتعريفات النقابات المجهولة الأعضاء. ما لم يتم إنشاء مثيل أو تخصص بشكل صريح أو تخصصه بشكل صريح ، يتم إنشاء تخصص العضو ضمنيًا عند الإشارة إلى التخصص في سياق يتطلب تعريف العضو ؛ على وجه الخصوص ، لا يحدث التهيئة (وأي آثار جانبية مرتبطة) لعضو بيانات ثابتة ما لم يتم استخدام عضو البيانات الثابتة نفسه بطريقة تتطلب تعريف عضو البيانات الثابتة.

"تعريفك الأول" للعضو الثابت ليس سوى إعلان - إليك اقتباس من المعيار.

15 تخصص صريح لعضو بيانات ثابت في القالب هو تعريف إذا كان الإعلان يتضمن مُهيئًا ؛ خلاف ذلك ، إنه إعلان. [ملاحظة: لا يوجد بناء جملة لتعريف عضو بيانات ثابت في قالب يتطلب التهيئة الافتراضية. قالب <> x س :: x ؛ هذا إعلان بغض النظر عما إذا كان يمكن تهيئة X (8.5).

يجب أن يعمل التعريف الثاني. هل أنت متأكد من أن لديك كل شيء متاح في وحدة تجميع واحدة؟ ما هو النص الدقيق لرسالة الخطأ؟

يجمع/تشغيل/تشغيل مع G ++ - الكل في ملف واحد

#include <iostream>

template < class T >
class MyClass
{
  public:
    static T staticObject;
    static T * staticPointerObject;
};

template < class T >
T MyClass<T>::staticObject;

template < class T >
T * MyClass<T>::staticPointerObject = 0; 

int main(int argc, char **argv)
{
  int an_int = 5;
  MyClass<int>::staticPointerObject = &an_int;
  std::cout << *MyClass<int>::staticPointerObject << std::endl;

  char a_char = 'a';
  MyClass<char>::staticPointerObject = &a_char;
  std::cout << *MyClass<char>::staticPointerObject << std::endl;
}

أستخدم الخدعة التالية طوال الوقت. الفكرة هي وضع ثابت في وظيفة ، والوصول إليها فقط من هذه الوظيفة. يتيح لك هذا النهج أيضًا تجنب الحاجة إلى إعلانك الثابت في أ .cpp ملف - كل شيء يمكن أن يعيش في .h ملف. بعد رمز المثال الخاص بك:

template < class T >
class MyClass
{
  public:
    static T * getObject() {
      // Initialization goes here.
      static T * object = NULL; // or whatever you want
      return pointerObject;
    }
};
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top