C ++ الفرق بين نوع التحويل التلقائي إلى STD :: سلسلة وشار *

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

سؤال

ونتيجة لممارسة التعلم، لقد كنت تبحث في كيفية عمل نوع التحويل التلقائي في C ++. I <م> معرفة هذا النوع التحويل التلقائي ينبغي تجنب عموما، ولكن أود أن زيادة معرفتي C ++ من خلال فهم كيف يعمل على أي حال.

ولقد خلقت طبقة StdStringConverter التي يمكن تحويلها تلقائيا إلى std::string، ولكن المترجم (ز ++ 4.3.4 على ديبيان) لا يبدو للقيام التحويل عند مقارنة الكائن ضد std::string الحقيقي (يرجى تجاهل عدم وجود يمر على حدة المرجعية وخلق لا لزوم له من الكائنات المؤقتة):

#include <string>

class StdStringConverter
{
public:
    explicit StdStringConverter(std::string name) : m_name(name) {}
    operator const std::string () const { return m_name; }
private:
    std::string m_name;
};

int main()
{
    StdStringConverter converter(std::string("Me"));
    const std::string name = "Me";
    // Next line causes compiler error:
    // no match for 'operator==' in 'converter == name'
    return (converter == name) ? 0 : 1;
}

من ناحية أخرى، إذا كنت تغييره قليلا إلى فئة CStringConverter، التحويل التلقائي <م> لا تجري، على الرغم من مقارنة مؤشرات char ربما ليس ما كنت أنوي:

#include <string>

class CStringConverter
{
public:
    explicit CStringConverter(std::string name) : m_name(name) {}
    operator const char* () const { return m_name.c_str(); }
private:
    std::string m_name;
};

int main()
{
    CStringConverter converter(std::string("Me"));
    const char* name = "Me";
    // Next line compiles fine, but they are not equal because the
    // pointers don't match.
    return (converter == name) ? 0 : 1;
}

هل هناك شيء خاص حول الفرق بين std::string وchar* في هذا السياق أن يجعل المترجم لا يعاملهم نفس الشيء؟

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

المحلول

والمشكلة هي بسبب الأمراض المنقولة جنسيا حقيقة :: سلسلة هو في الواقع مثيل قالب فئة الأمراض المنقولة جنسيا :: basic_string. و== المشغل المتوفرة في الأمراض المنقولة جنسيا مساحة يأخذ اثنين من القوالب الأمراض المنقولة جنسيا :: basic_string:


template<class charT, class traits, class Allocator>
bool operator==(const basic_string& lhs,
                const basic_string& rhs);

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

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

وشيء واحد يمكنني أن أقترح هو بالنسبة لك لوضع StdStringConverter في مساحة اسم وتقديم نسخة من == المشغل لالأمراض المنقولة جنسيا :: سلسلة في أن مساحة الاسم. بهذه الطريقة، عندما المترجم الخاص بك تجد تعبيرا من هذا القبيل ADL (حجة بحث تابع) يأتي دور ويعمل كل شيء على ما يرام.


#include <string>

namespace n1 {

class StdStringConverter
{
public:
    explicit StdStringConverter(std::string name) : m_name(name) {}
    operator std::string () { return m_name; }
private:
    std::string m_name;
};

bool operator==(std::string const& a, std::string const& b)
{
  return a == b; //EDIT: See Paul's comment on std::operator== here.
}

}

int main()
{
    using namespace n1;
    StdStringConverter converter(std::string("Me"));
    std::string name = "Me";
    return (converter == name) ? 0 : 1;   
}

نصائح أخرى

في المثال الأول فئتين مقارنة (سلسلة وStdStringConverter) لا يحصلون على أي معاملة خاصة من مترجم لنوع تحويل. وهذا يعني الزائد مشغل قمت بها حتى لا يحصل اثار. المترجم يبدو من خلال قائمة المشغل == الزائدة وغير منهم تأخذ في StdStringConverter لذلك يصرخ عليك.

في المثال الثاني الاسم هو شار *. نظرا لأنه هو نوع بدائي ثم يحاول المترجم لتحويل غير البدائية وصولا الى شار *. منذ لديك تجاوز في مكان عمله وقارنت العناوين.

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

#include <string>

class StdStringConverter
{
public:
    StdStringConverter(std::string name) : m_name(name) {}
    bool operator==(const StdStringConverter &name) { return m_name == name.m_name; }
    operator const std::string () const { return m_name; }
private:
    std::string m_name;
};

int main()
{
    StdStringConverter converter(std::string("Me"));
    const std::string name = "Me";
    // Next line causes compiler error:
    // no match for 'operator==' in 'converter == name'
    return (converter == name) ? 0 : 1;
}

والآن البرنامج بإرجاع 0. منذ منشئ هو الآن ليس واضحا فإن المترجم يحاول استخدامه لتحويل السلسلة إلى StdStringConverter. منذ الآن هناك == المشغل في أعمال كل شيء StdStringConverter.

وهناك عوامل متعددة. إذا قمت بتغيير بيان عودة thusly

وعودة (الأمراض المنقولة جنسيا :: المشغل == (الاسم، اسم))؟ 0: 1؛

وذلك برمجيا، على الرغم من أنه من الواضح أنها لا تفعل الشيء نفسه. من ناحية أخرى

وعودة (الأمراض المنقولة جنسيا :: المشغل == (المحول، اسم))؟ 0: 1؛

ولكن لا يوفر رسالة الخطأ أكثر إثارة للاهتمام

وأي وظيفة مطابقة لدعوة إلى '== المشغل (StdStringConverter و، CONST الأمراض المنقولة جنسيا :: سلسلة و)

والذي يذكرني هذا المشغل == هو قالب على basic_string <>، الذي يضم ثلاثة المعلمات قالب للإقلاع. إذا كنت تستخدم الباحث في المثال الخاص بك بدلا من STD :: سلسلة، المترجم لا يشكو.

وكيفية الحصول على النتيجة المرجوة مع الأمراض المنقولة جنسيا :: سلسلة هو أكثر إثارة للاهتمام ...

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