فقدت وظيفة العضو المتخصص بعد الارتباط من خلال ar

StackOverflow https://stackoverflow.com//questions/12681622

  •  12-12-2019
  •  | 
  •  

سؤال

خذ بعين الاعتبار المثال البسيط التالي الذي يعيد إنتاج مشكلة في مشروع أكبر بكثير:

المواصفات.ح:

#include <iostream>

class A
{
public:
    template<typename T>
    T test(const std::string& a)
    {
        std::cout << "DEFAULT CALLED WITH " << a << "\n";
        return T();
    }
};

أخرى.cpp:

#include "spec.h"

template<>
float A::test<float>(const std::string& a)
{
    std::cout << "SPECIAL CALLED WITH " << a << "\n";
    return float();
}

المواصفات.CPP:

#include <iostream>
#include "spec.h"

int main()
{
    A a;
    a.test<int>("int");
    a.test<float>("float");
    return 0;
}

التحويل البرمجي:

$ make
rm -f *.o lib.a output
clang++ -g other.cpp -c
clang++ -g spec.cpp -c
ar cr lib.a other.o
clang++ -g -o output lib.a spec.o
rm -f *.o output2
clang++ -g other.cpp -c
clang++ -g spec.cpp -c
clang++ -g -o output2 other.o spec.o

$ ./output
DEFAULT CALLED WITH int
DEFAULT CALLED WITH float

$ ./output2
DEFAULT CALLED WITH int
SPECIAL CALLED WITH float

سؤال:

لماذا يحدث هذا؟هل يتم تجريده بطريقة ما؟ما الفرق بين lib.a واستخدام ملف الكائن المباشر؟:-)

شكرًا!

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

المحلول

من القسم 14.7.3ص6:

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

برنامجك غير مُصمم لأنك استخدمت التخصص في spec.cpp دون الإعلان عنه أولاً في وحدة الترجمة تلك.أو كما تقول الفقرة التالية:

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

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

الذي أصوت له كما الأروع فقرة ليمريك في المعيار كله.

نصائح أخرى

إجابة بن Voigt صحيحة، لكنني أريد أن أضيف قليلا إليه.

لديك أساسا الحصول على نسختين مختلفتين من الوظيفة، واحدة داخل أخرى .o وواحد في المواصفات .o (الناتج عن القالب المضمن).تم تصميم الرابط لاختيار واحد وواحد فقط، مما يجعل الافتراض أنهم متطابقين كما يتطلب المعيار.في الحالة الأولى، سيسحب الرابط تعريفا فقط من مكتبة إذا لم يتم تعريف الرمز بالفعل.نظرا لأنه محدد في المواصفات، فلن يتم استخدام تعريف المكتبة.

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

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