wake-up-neo.com

Gibt ein "NULL" -Objekt zurück, wenn das Suchergebnis nicht gefunden wurde

Ich bin ziemlich neu in C++, daher neige ich dazu, während des Lernens mit vielen Java-Ismen zu entwerfen. Auf jeden Fall würde ich in Java, wenn ich eine Klasse mit einer 'search'-Methode hätte, die ein Objekt T von einem Collection< T > Zurückgibt, das einem bestimmten Parameter entspricht, dieses Objekt zurückgeben, und wenn das Objekt dies wäre nicht in der Sammlung gefunden, würde ich null zurückgeben. Dann würde ich in meiner aufrufenden Funktion nur if(tResult != null) { ... } überprüfen

In C++ stelle ich fest, dass ich keinen null -Wert zurückgeben kann, wenn das Objekt nicht vorhanden ist. Ich möchte nur einen Indikator vom Typ T zurückgeben, der der aufrufenden Funktion mitteilt, dass kein Objekt gefunden wurde. Ich möchte keine Ausnahme auslösen, weil es nicht wirklich ein außergewöhnlicher Umstand ist.

So sieht mein Code im Moment aus:

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;
}

Wie kann ich es ändern, damit ich diese Art von Marker geben kann?

90
aduric

In C++ dürfen Referenzen nicht null sein. Wenn Sie optional null zurückgeben möchten, wenn nichts gefunden wird, müssen Sie einen Zeiger zurückgeben, keinen Verweis:

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

Wenn Sie andernfalls darauf bestehen, als Referenz zurückzukehren, sollten Sie eine Ausnahme auslösen, wenn das Attribut nicht gefunden wird.

(Übrigens mache ich mir ein wenig Sorgen, dass Ihre Methode const ist und ein Attribut zurückgibt, das nicht const ist. Aus philosophischen Gründen würde ich vorschlagen, const Attr *. Wenn Sie dieses Attribut auch ändern möchten, können Sie eine Überladung mit einer nicht-const -Methode ausführen, die auch ein nicht-const -Attribut zurückgibt.)

65
Jesse Beder

Hier gibt es mehrere mögliche Antworten. Sie möchten etwas zurückgeben, das möglicherweise vorhanden ist. Hier sind einige Optionen, die von meinen am wenigsten bevorzugten bis zu den am meisten bevorzugten reichen:

  • Rückgabe als Referenz und Signal kann ausnahmsweise nicht gefunden werden.

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

Es ist wahrscheinlich, dass das Nichtfinden von Attributen ein normaler Teil der Ausführung ist und daher nicht sehr außergewöhnlich. Die Handhabung hierfür wäre laut. Ein Nullwert kann nicht zurückgegeben werden, da es undefiniert ist, Nullreferenzen zu haben.

  • Rückkehr mit dem Zeiger

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

Es ist leicht zu vergessen, zu überprüfen, ob ein Ergebnis von getAttribute ein Nicht-NULL-Zeiger ist und eine leichte Fehlerquelle darstellt.

  • Verwenden Sie 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&>();
    }

Ein boost :: optional zeigt genau an, was hier vor sich geht, und bietet einfache Methoden, um zu überprüfen, ob ein solches Attribut gefunden wurde.


Randnotiz: std :: optional wurde kürzlich in C++ 17 gewählt, so dass dies in naher Zukunft ein "Standard" sein wird.

55
Kaz Dragon

Sie können problemlos ein statisches Objekt erstellen, das eine NULL-Rückgabe darstellt.

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; 
};

Und irgendwo in einer Quelldatei:

static Attr AttrNull;
22
Mark Ransom

Wenn Sie einen NULL Rückgabewert wünschen, müssen Sie Zeiger anstelle von Referenzen verwenden.

Referenzen können selbst nicht NULL sein.

(Hinweis zu den zukünftigen Kommentar-Postern: Ja, Sie können die Adresse eines Verweises auf NULL setzen, wenn Sie es wirklich wirklich versuchen).

Siehe meine Antwort hier für eine Liste der Unterschiede zwischen Referenzen und Zeigern .

3
Brian R. Bondy

Da Sie herausgefunden haben, dass Sie es nicht so tun können, wie Sie es in Java (oder C #) getan haben. Hier ist ein weiterer Vorschlag, den Verweis des Objekts als Argument zu übergeben und zurückzugeben bool value. Wenn das Ergebnis in Ihrer Sammlung gefunden wird, können Sie es der übergebenen Referenz zuweisen und 'true' zurückgeben, andernfalls 'false' zurückgeben. Bitte beachten Sie diesen Code.

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;
}

Die obige Funktion muss den Operator anhand des Schlüssels 'token' finden, wenn sie denjenigen findet, den sie zurückgibt, und den Wert dem Parameter Operator & op zuweisen.

Der Anrufercode für diese Routine sieht folgendermaßen aus

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

Der Grund, warum Sie hier nicht NULL zurückgeben können, ist, dass Sie Ihren Rückgabetyp als Attr& Deklariert haben. Das nachfolgende & Macht den Rückgabewert zu einer "Referenz", die im Grunde genommen ein Zeiger auf ein vorhandenes Objekt ist, der garantiert nicht null sein darf. Wenn Sie null zurückgeben möchten, ändern Sie Attr& In Attr*.

1
JSBձոգչ

Sie können NULL nicht zurückgeben, da der Rückgabetyp der Funktion ein Objekt reference und kein pointer ist.

0
codaddict