سؤال

أحاول تنفيذ طريقة شجرة ثنائية والتي ترجع تيار.أريد أن استخدام تيار عاد في طريقة عرض الشجرة في الشاشة أو لإنقاذ شجرة في ملف:

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

الإعلانات:

void streamIND(ostream&,const BinaryTree<T>*);
friend ostream& operator<<(ostream&,const BinaryTree<T>&);

template <class T>
ostream& operator<<(ostream& os,const BinaryTree<T>& tree) {
    streamIND(os,tree.root);
    return os;
}

template <class T>
void streamIND(ostream& os,Node<T> *nb) {
    if (!nb) return;
    if (nb->getLeft()) streamIND(nb->getLeft());
    os << nb->getValue() << " ";
    if (nb->getRight()) streamIND(nb->getRight());
}

هذا الأسلوب هو في UsingTree الدرجة:

void UsingTree::saveToFile(char* file = "table") {
    ofstream f;
    f.open(file,ios::out);
    f << tree;
    f.close();
}

لذا طاقتها المشغل "<<"من بيناريتري فئة الاستخدام:cout << شجرة ofstream f << شجرة لكني تتلقى رسالة الخطأ التالية:غير معرف الإشارة إلى `المشغل<<(std::basic_ostream >&, بيناريتري&)'

P. S.شجرة مخازن كلمة الكائنات (سلسلة مع الباحث).

أرجو أن تفهم إنجليزية.شكرا لك!و أود أن أعرف نص جيد للمبتدئين حول المحكمة الخاصة بلبنان التي تشرح كل ما يلزم لأنني أضيع كل وقتي في أخطاء من هذا القبيل.

تحرير:شجرة في saveToFile() يعلن:بيناريتري< كلمة > شجرة.

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

المحلول

المشكلة هي أن المترجم ليس محاولة استخدام قالب operator<< قدمت لك وإنما غير قالب نسخة.

عندما تقوم بتعريف صديق داخل الطبقة كنت بالحقن الإعلان عن تلك الوظيفة في أرفق نطاق.التعليمة البرمجية التالية له تأثير إعلان (ولا تحديد) مجانا وظيفة أن يأخذ non_template_test حجة من الإشارة المستمرة:

class non_template_test
{
   friend void f( non_template_test const & );
};
// declares here:
// void f( non_template_test const & ); 

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

template<typename T>
class template_test
{
    friend void f( template_test<T> const & t );
};
// for each instantiating type T (int, double...) declares:
// void f( template_test<int> const & );
// void f( template_test<double> const & );

int main() {
    template_test<int> t1;
    template_test<double> t2;
}

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

template<typename T> class template_test {
   friend void f( template_test<T> const & );
};
// when instantiated with int, implicitly declares:
// void f( template_test<int> const & );

template <typename T>
void f( template_test<T> const & x ) {} // 1

int main() {
   template_test<int> t1;
   f( t1 );
}

عندما مترجم يضرب الرئيسية وظيفة instantiates القالب template_test مع نوع int وأن تعلن عن وظيفة خالية void f( template_test<int> const & ) ليس هذا هو قالب.عندما يجد الدعوة f( t1 ) هناك نوعان من f الرموز التي تطابق:غير قالب f( template_test<int> const & ) المعلنة (غير معرف) عندما template_test تم إنشاء مثيل و قالب النسخة التي هي على حد سواء المعلنة والمحددة في 1.غير قالب نسخة الأسبقية و مترجم المباريات.

عندما رابط يحاول حل غير قالب نسخة من f فإنه لا يمكن العثور على رمز وبالتالي فشل.

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

وجود مترجم تولد غير قالب وظائف لنا:

template <typename T>
class test 
{
   friend void f( test<T> const & ) {}
};
// implicitly

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

صنع قالب النسخة صديق

لجعل القالب صديق يجب أن يكون ذلك أعلنت بالفعل و يخبر المترجم أن صديق نريد فعلا قالب و لا غير قالب وظيفة خالية:

template <typename T> class test; // forward declare the template class
template <typename T> void f( test<T> const& ); // forward declare the template
template <typename T>
class test {
   friend void f<>( test<T> const& ); // declare f<T>( test<T> const &) a friend
};
template <typename T> 
void f( test<T> const & ) {}

في هذه الحالة, قبل أن يعلن f كنموذج يجب أن الأمام تعلن القالب.تعلن f القالب يجب علينا أولا إلى الأمام تعلن test القالب.صديق إعلان تعديل تشمل أقواس زاوية أن تحديد هذا العنصر ونحن نبذل صديق هو في الواقع القالب وليس وظيفة مجانا.

العودة إلى المشكلة

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

template <typename T>
class BinaryTree {
   friend std::ostream& operator<<( std::ostream& o, BinaryTree const & t ) {
      t.dump(o);
      return o;
   }
   void dump( std::ostream& o ) const;
};

مع هذا الرمز هي مما اضطر المترجم إلى توليد غير قالب operator<< لكل مثيل من النوع التي ولدت وظيفة مندوبين على dump طريقة القالب.

نصائح أخرى

وأنت لا تحتاج إلى إعلان المشغل قالب وعليك أن يعلن المشغل "صديق" لفئة أن يكون لديك منح الوصول إلى الفئات الأخرى، في هذه الحالة الأمراض المنقولة جنسيا :: cout

friend std::ostream& operator << ( std::ostream& os, BinaryTree & tree )
{
    doStuff( os, tree );
    return os;
}

والقراءة أوصت: http://www.parashift.com/c++- أسئلة وأجوبة لايت / friends.html

عند الحمولة الزائدة المشغل << تريد استخدام مرجع CONST:

template <class T>
std::ostream& operator << (std::ostream& os, const BinaryTree<T>& tree) 
{
    // output member variables here... (you may need to make
    // this a friend function if you want to access private
    // member variables...

    return os;
}

تأكد من تعريفات قالب كامل (وليس نماذج أولية فقط) في ملف التضمين (أي. ح، .hpp) كقوالب وتجميع منفصل لا تعمل معا.

وأنا لا أعرف ماDribeas رابط يستخدم، ولكن هذا يمكن أن يسبب بالتأكيد رابط GNU لإعطاء إشارة خطأ غير محدد.

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