إرجاع كائن "فارغ" إذا لم يتم العثور على نتيجة البحث

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

  •  26-09-2019
  •  | 
  •  

سؤال

أنا جديد جدًا على C ++ ، لذا أميل إلى التصميم مع الكثير من Java-Imms أثناء التعلم. على أي حال ، في Java ، إذا كان لدي فئة مع طريقة "بحث" من شأنها أن تعيد كائن T من Collection< T > تتوافق مع معلمة محددة ، أود أن أعيد هذا الكائن وإذا لم يتم العثور على الكائن في المجموعة ، فسأعود null. ثم في وظيفة الاتصال الخاصة بي ، سوف أتحقق فقط if(tResult != null) { ... }

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

هذا ما يبدو عليه الكود الخاص بي الآن:

class Node {
    Attr& getAttribute(const string& attribute_name) const {
       //search collection
       //if found at i
            return attributes[i];
       //if not found
            return NULL; // what should this be?
    }

private:
    vector<Attr> attributes;
}

كيف يمكنني تغييره حتى أتمكن من إعطاء هذا النوع من العلامات؟

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

المحلول

في C ++ ، لا يمكن أن تكون المراجع فارغة. إذا كنت ترغب في إرجاع اختياري NULL إذا لم يتم العثور على شيء ، فأنت بحاجة إلى إعادة مؤشر ، وليس مرجعًا:

Attr *getAttribute(const string& attribute_name) const {
   //search collection
   //if found at i
        return &attributes[i];
   //if not found
        return nullptr;
}

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

(بالمناسبة ، أنا قلق قليلاً من أن تكون طريقتك const وإعادة غيرconst ينسب. لأسباب فلسفية ، أقترح العودة const Attr *. إذا كنت ترغب أيضًا في تعديل هذه السمة ، فيمكنك الزائد مع غيرconst طريقة إرجاع غيرconst السمة كذلك.)

نصائح أخرى

هناك العديد من الإجابات المحتملة هنا. تريد إعادة شيء قد يوجد. فيما يلي بعض الخيارات ، بدءًا من الأقل تفضيلًا إلى الأكثر تفضيلًا:

  • العودة بالرجوع إليها ، وإشارة يمكن أن لا تكون الثقة عن طريق الاستثناء.

    Attr& getAttribute(const string& attribute_name) const 
    {
       //search collection
       //if found at i
            return attributes[i];
       //if not found
            throw no_such_attribute_error;
    }

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

  • العودة بواسطة المؤشر

    Attr* getAttribute(const string& attribute_name) const 
    {
       //search collection
       //if found at i
            return &attributes[i];
       //if not found
            return nullptr;
    }

من السهل أن ننسى التحقق مما إذا كانت نتيجة GetAttribute ستكون مؤشرًا غير فائق ، وهو مصدر سهلة للحشرات.

  • يستخدم Boost.Optional

    boost::optional<Attr&> getAttribute(const string& attribute_name) const 
    {
       //search collection
       //if found at i
            return attributes[i];
       //if not found
            return boost::optional<Attr&>();
    }

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


ملاحظة جانبية: تم التصويت على std :: اختياري مؤخرًا في C ++ 17 ، لذلك سيكون هذا شيئًا "قياسيًا" في المستقبل القريب.

يمكنك بسهولة إنشاء كائن ثابت يمثل عائدًا فارغًا.

class Attr;
extern Attr AttrNull;

class Node { 
.... 

Attr& getAttribute(const string& attribute_name) const { 
   //search collection 
   //if found at i 
        return attributes[i]; 
   //if not found 
        return AttrNull; 
} 

bool IsNull(const Attr& test) const {
    return &test == &AttrNull;
}

 private: 
   vector<Attr> attributes; 
};

وفي مكان ما في ملف المصدر:

static Attr AttrNull;

إذا كنت تريد أ NULL قيمة الإرجاع تحتاج إلى استخدام المؤشرات بدلاً من المراجع.

لا يمكن أن تكون المراجع نفسها NULL.

(لاحظ إلى ملصقات التعليقات المستقبلية: نعم ، يمكنك الحصول على عنوان مرجع يكون فارغًا إذا حاولت حقًا ذلك).

انظر إجابتي هنا للحصول على قائمة بالاختلافات بين المراجع والمؤشرات.

كما اكتشفت أنه لا يمكنك القيام بذلك بالطريقة التي قمت بها في Java (أو C#). فيما يلي اقتراح آخر ، يمكنك تمريره في مرجع الكائن كوسيطة وإرجاع قيمة منطقي. إذا تم العثور على النتيجة في مجموعتك ، فيمكنك تعيينها إلى المرجع الذي يتم تمريره وإرجاع "صحيح" ، وإلا فإن "خطأ". يرجى النظر في هذا الرمز.

typedef std::map<string, Operator> OPERATORS_MAP;

bool OperatorList::tryGetOperator(string token, Operator& op)
{
    bool val = false;

    OPERATORS_MAP::iterator it = m_operators.find(token);
    if (it != m_operators.end())
    {
        op = it->second;
        val = true;
    }
    return val;
}

يتعين على الوظيفة أعلاه العثور على المشغل مقابل "الرمز المميز" المفتاح ، إذا عثرت على تلك التي تُرجعها بشكل صحيح وتعيين القيمة لمشغل المعلمة و OP.

رمز المتصل لهذا الروتين يبدو هكذا

Operator opr;
if (OperatorList::tryGetOperator(strOperator, opr))
{
    //Do something here if true is returned.
}

السبب في عدم قدرتك على إعادة NULL هنا هو أنك أعلنت نوع الإرجاع الخاص بك كـ Attr&. الزائدة & يجعل قيمة الإرجاع "مرجعًا" ، وهو أساسًا مؤشرًا مضمونًا غير مضمون إلى كائن موجود. إذا كنت تريد أن تكون قادرًا على إعادة فارغ ، فقم بتغيير Attr& ل Attr*.

أنت غير قادر على العودة NULL لأن نوع الإرجاع للوظيفة هو كائن reference وليس pointer.

يمكنك تجربة هذا:

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