検索結果が見つからない場合は「NULL」オブジェクトを返します
-
26-09-2019 - |
質問
私は C++ についてはかなり初心者なので、学習中は Java 主義を多く取り入れて設計する傾向があります。とにかく、Javaで、オブジェクトを返す「search」メソッドを持つクラスがあったとします。 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; }
おそらく、属性が見つからないことは実行の通常の部分であり、したがってそれほど例外的なことではありません。これを扱うと騒音が大きくなります。null 参照を持つことは未定義の動作であるため、null 値を返すことはできません。
ポインタによる戻り
Attr* getAttribute(const string& attribute_name) const { //search collection //if found at i return &attributes[i]; //if not found return nullptr; }
getAttribute の結果が非 NULL ポインターであるかどうかを確認することは忘れられやすく、バグの原因となりやすいです。
使用 ブースト.オプション
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&>(); }
boost::optional は、ここで何が起こっているかを正確に示し、そのような属性が見つかったかどうかを検査する簡単なメソッドを備えています。
サイドノート:std::optional は最近 C++17 に組み込まれることが投票されたため、これは近い将来「標準」になるでしょう。
あなたは簡単にNULLリターンを表し、静的オブジェクトを作成することができます。
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
することはできません。
(将来のコメントポスターの注:はい、あなたが本当にしようとした場合、参照のアドレスがNULLになることができます)。
。ここでは、引数と戻りbool値としてオブジェクトの参照を渡すことができ、別の提案は、あります。結果はあなたのコレクションで発見された場合は、そうでない場合は「偽」を返し、渡されるリファレンスとリターン「真」にそれを割り当てることができます。このコードを検討してください。
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;
}
上記の関数は、それがtrueを返し、パラメータ演算子&OPに値を割り当てるものを見つけた場合、キー「トークン」に対してオペレータを見つけることがあります。
このように、このルーチンルックスの発信者コード
Operator opr;
if (OperatorList::tryGetOperator(strOperator, opr))
{
//Do something here if true is returned.
}
Attr&
として、あなたの戻り値の型を宣言したため、あなたがここにNULLを返すことができないという理由があります。後続&
は、戻り値を、基本的に既存のオブジェクトへの保証はなくツーことがヌルポインタである「参照」を作ります。あなたはAttr&
にヌル、変更Attr*
を返すことができるようにしたい場合。
あなたは、関数の戻り値の型がオブジェクトNULL
なくreference
あるのでpointer
を返すことができません。
あなたはこれを試すことができます
return &Type();