سؤال

لدي فئة ذات طريقة ثابتة تشبه:

class X {
    static float getFloat(MyBase& obj) {
        return obj.value();  // MyBase::value() is virtual
    }
};

أنا أسميها بمثال من الفئات الفرعية MyBase:

MyDerived d;
float f = X::getFloat(d);

إذا قمت بربط ملف OBJ الذي يحتوي على X في بلدي القابل للتنفيذ ، كل شيء يعمل كما هو متوقع. إذا كنت أتوقع الحصول على 3.14 ، أحصل عليه.

إذا قمت بإنشاء .lib الذي يحتوي على ملف X.OBJ وربطه في .lib ، فإنه يكسر. عندما أدعو getFloat () ، فإنه يعود -1.#ind00. هل هذا نوع من قيمة الحارس يجب أن تخبرني ما هو الخطأ هنا؟

هل هناك أي شيء مختلف عند الارتباط في LIB بدلاً من OBJ مباشرة؟

لا أحصل على أي تحذيرات أو أخطاء برمجية.

يحرر:
أنا أستخدم Visual Studio 2005 على Windows XP Pro SP3. للتأكد من أنني لم أكن أربط الملفات القديمة ، قمت باستنساخ طريقة Value () في طريقة Value2 () جديدة ودعت ذلك بدلاً من ذلك. كان السلوك هو نفسه.

تحرير #2:
لذا ، إذا تتبعت في المكالمة مع تصحيح الأخطاء الخاصة بي ، فأنا أجد أنه لا يحدث في طريقة قيمتي () على الإطلاق. بدلاً من ذلك ، فإنها تسير في طريقة مختلفة (غير ذات صلة). هذا يجعلني أعتقد أن vtable تالفة. أعتقد أن السلوك الذي أراه يجب أن يكون تأثيرًا جانبيًا لمشاكل أخرى.


تم حلها! (بفضل فلاد)
اتضح أنني كنت انتهك قاعدة التعريف الواحد (ODR) على الرغم من أنها لم تكن واضحة من القانون الذي نشرته. هذه هي مقالة رائعة من اللاعبين المرئيين C ++ الذي يشرح المشكلة وطريقة واحدة لتتبعها. ال /d1reportsingleclasslayout العلم المترجم هو أداة تعليمية رائعة.

عندما قمت بإلغاء تخطيط الفصل الخاص بي لـ MyBase و MyDerived في المشروعين المختلفين ، وجدت اختلافات بين رمز الاتصال ورمز المكتبة. اتضح أن لدي بعض #ifdef كتل في ملفات Header والمقابلة #حدد كان البيان في الرأس المسبق للمشروع الرئيسي ولكن ليس في المشروع الفرعي (المكتبة). هل ذكرت كم أعتقد أن وحدات الماكرو المسبقة للشر؟

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

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

المحلول

ستحدث هذه المشكلة عندما يتم تجميع LIB والقابلة للتنفيذ تعريفات مختلفة من MyDerived صف دراسي (أي إصدارات مختلفة من .h/.hh/.hpp ملف يعلن MyDerived. نظيفة تماما وإعادة بناء مشاريعك. باستثناء هذا ، خيارات البرمجيات المختلفة استطاع كن مسؤولاً ، على الرغم من أنه من غير المحتمل إلى حد ما.

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

نصائح أخرى

نظرًا لأن LIB مجرد حاوية ، إذا كنت تربط ملف .OBJ نفسه في كلتا الحالتين ، فإن براين يقول إنه لا ينبغي (لا يمكن؟) أن يكونوا فرقًا.

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

لا ينبغي أن يكون هناك فرق. فقط تأكد من أن ملفات .h التي تضمنها تتوافق مع .lib التي تربطها بالضبط. أظن أنك قد تربط ملف .lib قديم.

إذا كنت تستخدم Visual Studio ، بدلاً من تحديد ملف .lib بشكل صريح ، فما عليك سوى النقر بزر الماوس الأيمن على المشروع وتعيين التبعيات على مشروع .lib. وبهذه الطريقة سوف تكون متأكدًا من أنه يستخدم ملف .lib الصحيح.

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