2017-07-19 7 views
-1

こんにちは私は学習目的でさまざまな抽象データ型を開発する学生です。私はこれらのADTのキーを調べるために添え字演算子をオーバーロードしようとしています。私のコードが欠けているキーを挿入するケースを避けることはできません。C++ overloading subscript dereference where nullptrが許可されています

これらのADTから読み込む場合、nullptrの戻り値はキーが見つからなかったことを示します。私は私のADTの書き込みまたは挿入時にのみ新しいキーを追加したい。

ここ
const char *x = tree["key"]; 

「キーは」私はこのキーを追加しないと、その不在を示すためにnullptrを戻したい見つからない場合:私のコードは次のことをどのように扱うかで間違っています。キーは次の状況でのみ追加する必要があります。

tree["key"] = "x"; 

これは非常に微妙なバグです。次のテストはtrueを返しますが、テストされる値はhash ["key"] .val(nullになることがあります)であるためです。

if (!x) printf("%s not found!\n", "key"); 

これはconstを使用して実現でき、以下のシグネチャを使用していると思います。

char const *operator[](char *index) const; 

このconstオーバーロードは実行されません。なぜこれが事実であり、適切に動作するサンプルシグネチャ(またはこのオーバーロードを評価するようにする例)のいずれかを説明することができますか。ここに私のコードは次のとおりです。tree["key"] = "x";よりもあなたがtree["key"]const char *x = tree["key"];で異なる動作をしたい

#include <stdio.h> 
#include <string.h> 

class lookup { 
    lookup *left; 
    lookup *right; 
    char *key; 
    char *val; 

public: 
    lookup(char *k) { 
     left = nullptr; 
     right = nullptr; 
     val = nullptr; 
     key = new char[strlen(k)+1]; 
     strcpy(key, k); 
    } 

    ~lookup() { 
     if (key) delete key; 
     if (val) delete val; 
    } 

    /* read/write access */ 
    /* if the key does not exist, then create it */ 
    char *&operator[](char *index) { 
     printf(" []= x\n"); 

     int x = strcmp(index, key); 
     if (x < 0) { 
      if (left == nullptr) left = new lookup(index); 
      return (*left)[index]; 
     } 
     if (x > 0) { 
      if (right == nullptr) right = new lookup(index); 
      return (*right)[index]; 
     } 
     return val; 
    } 

    /* read only access */ 
    /* if the key does not exist, then return nullptr (not found) */ 
    char const *operator[](char *index) const { 
     printf(" x = *[]\n"); 

     int x = strcmp(index, key); 
     if (x < 0) { 
      if (left == nullptr) return nullptr; 
      else return (*left)[index]; 
     } 
     if (x > 0) { 
      if (right == nullptr) return nullptr; 
      else return (*right)[index]; 
     } 
     return val; 
    } 
}; 

int main(void) { 
    lookup tree("root"); 

    /* this creates the key (which is not intended) */ 
    const char *x = tree["key"]; 
    if (!x) printf("%s not found!\n", "key"); 

    /* only now should the key be created */ 
    tree["key"] = "value"; 
    return 0; 
} 
+0

あなたが 'new []'で何かを割り当てる場合、 'delete []'で解放する必要があることに注意してください。また、Cスタイルの文字列の代わりにstd :: stringsを使用すると、コードがはっきりと簡単になります。 –

+0

'if(key)delete key;' - 誤った形式の 'delete'です。それは 'delete []'でなければなりません。これを避け、単に 'std :: string'を使用してください。 – PaulMcKenzie

+0

*このconstのオーバーロードは決して呼び出されません。* 'lookup'を関数へのconst参照として渡し、その関数内で' lookup :: operator [] 'を呼び出そうとします。コンパイルには 'const'バージョンを呼び出す以外に選択肢はありません。 – PaulMcKenzie

答えて

1

。それだけでは不可能です。ステートメント内のサブ式の位置は、そのサブ式がどのように振る舞うかに影響しません。

サブスクリプト演算子の戻り値の型を変更できる場合、あなたが探しているのと同じような振る舞いをするかもしれません。不足している値をツリーに追加することがなく、代入時に要素を追加する動作を持つオブジェクトを返すことができない場合は、上記の2つのステートメントを使用して好きなように動作させることができます。

しかし、上記は実装するのが難しく、警告がある可能性があります。おそらく、あなたはミス時に挿入することなくオブジェクトを検索するためにoperator[]を使用する必要はありません。オーバーロードを使用する代わりに、別の関数を使用してより簡単に行うことができます。たとえば、std::mapのようにポールが提案したものです。

関連する問題