2016-07-06 11 views
-2

ポインタが「プライベート」のときにポインタを使用する方法を理解できない。リンクされたリストのプライベートポインタC++

ほとんど私が取得し、ポインタ

私は文字値を持っていない頭と尾のノードを作成したい

の値を設定する方法がわかりません。 次に、headとtailの間にある新しいノードを作成し、新しいノードをリストの最後(tailの前)に追加します。

コードは実行されますが、印刷機能を使用すると何も実行されません。

申し訳ありませんが、私の書式が間違っていて、コードが長すぎる場合。ここ

は私のクラスのコードです:ここ

#include <iostream> 
using namespace std; 

class node 
{ 
public: 
    node(void)// constructor for empty nodes 
    { 
    left_link = NULL; 
    right_link = NULL; 
    } 
    node(char x) // constructor for nodes with given value 
    : anything(x) 
    { } 
    char get_char() // return character 
    { 
    return anything; 
    } 
    void setLeftLink(node *left) 
    { 
    left_link = left; 
    } 
    void setRightLink(node *right) 
    { 
    right_link = right; 
    } 
    node *getlefttLink() 
    { 
    return left_link; 
    } 
    node *getRightLink() 
    { 
    return right_link; 
    } 

private: 
    node *left_link; 
    char anything; 
    node *right_link; 
}; 

は私の関数です:

int main() 
{ 
char choice; 
node *head = new node; 
node *tail = new node; 

cout << "Please choose one menu option at a time:\n" 
    << "1 = Append\n" 
    << "2 = Print list\n" 
    << "3 = Exit\n\n"; 


    do 
    { 
     cout << "Menu option(1-3): "; 
     cin >> choice; 

     switch (choice) 
     { 
      case '1': append(head, tail); // add to the end of list. 
       break; 
      case '2': print(head); // print list 
       break; 
      case '3': cout << "end program\n\n"; 
       break; 
      default: cout << "try again\n"; 
       break; 
     } 


    }while(choice != '3'); 

return 0; 
} 
+0

私はあなたの問題は、変数がプライベートであることとは何かを持っている疑い。 – immibis

+0

***コードは実行されますが、print関数を使用すると何もしません。***あなたのアドバイスは、デバッガの使用方法を学ぶことです。変数を見ているコードを一歩。 – drescherjm

+0

あなたはリンクリスト概念かC++ポインタを誤解しています。要素がない場合は、新しいノードを作成しなければなりません。新しいノードはheadとtailの両方になり、それを 'nullptr'に左右隣に設定します。'append'関数内の' if'文を見直してください。**未定義の動作**があります。 – K117

答えて

0

privateメンバー、ポインタまたはその他のものは、オブジェクトが誰かに混乱したくない、または誰かが混乱しているかどうかを知りたいデータです。

セッターメソッドとゲッターメソッドは、privateメンバへのアクセスを制御された方法で許可します。たとえば、決して十数を超えることができないプライベート整数がある場合、呼び出し側が値を範囲外に強制して要求を拒否しようとしているかどうかをチェックするコードをセッターに含めることができます。

bool setX(int newX) 
{ 
    if (newX > 10) 
    { 
     return false; 
    } 
    else 
    { 
     X = newX; 
     return true; 
    } 
} 

今プログラムは、範囲外のアクセスまたは任意の原因となるXの== 11で任意の厄介な驚きを持つことができません。

これはオブジェクトの自己防御です。彼らは、誰がデータを何に設定し、一貫性を維持できるかを管理しています。 CPUを枯渇させずにシステムをロックすることなく、FIRフィルタを有効にして1秒間に10000を超えるサンプルでA/Dをサンプリングできないという複雑なケースがあるとします。うわー。 Filter状態またはサンプリングレートを設定する唯一の方法がA/Dマネージャオブジェクトのセッターを介している場合、オブジェクトはテストと拒否を行い、災害を防ぎます(悪い俳優を指すファットログメッセージを残すこともできます)。

定数でない参照やポインタを返すゲッターを実装する前に、非常に難しいと思ってください。呼び出し元にどちらかがあると、返されたデータで必要な処理を実行できます。

親切な理由なしにデータへのアクセスを許可しないで、セッターとゲッターを介して制御されたアクセスを優先するのがパラノイアです。

問題の詳細については、

リンクノードのゲッターとセッターは、しばしば嫌な賭けです。リンケージが有効である場合、ノードは自分自身を決定できない可能性が最も高い。リストマネージャのみが可能です。これは、オブジェクト自体が何が安全であるかを知るにはあまりにも無知であるため、より多くを知っている別のオブジェクトに内部を開く必要があります。 friendは便利ですが、ノードのリンクpublicを作成し、リストマネージャがノードをクライアントに与えることを許可しないことがよくあります。

オッズは良好です。クライアントはリストの仕組みについて絶対に何も知ってはいけません。カップリングで読む。

したがってノードは完全に愚かでなければなりません。つまり、ListManagerクラス(リスト)を管理して、リストを管理し、悪い振る舞いをするアクターからnodeを保護する必要があります。

ListManagerはあなたのheadtailappendremoveとともにrootまたは何、printおよびその他のリスト管理メソッドが含まれています。いかなる状況下でも、これらの関数のいずれも呼び出し元にnodeを明らかにしませんが、呼び出し元にリストを損傷させることなくノードを参照するためのハンドルまたはイテレータを返すことはできません。イテレータは独自の質問にふさわしいトピックであり、すでにかなりの数のものがあります。

上記を説明するコードの一部が順番です。私が見つけた論理的な問題はマークしましたが、修正されていません。これがコンパイルされると(C++ 11を有効にして)さらに多くなることがありますが、実行していません。

class ListManager 
{ 
private: 
    class node 
    { 
    public: 
     node *left_link = nullptr; // recommendation: immediately set or NULL all 
            // pointers unless you have a well documented 
            // reason not to and profiling to back it up. 
            // The time you save can be enormous. 
     char anything; 
     node *right_link = nullptr; 
    }; 
    node *head = nullptr; 
    node *tail = nullptr; 

public: 

    void append(char c) // head and tail not required ListManager members 
    { 
     /* removed because the append function should append and only append. 
     * If you want to read data from the user, call a read function first 
     * and pass it read character in to append 
     * Do one thing and do it well. Every time you add behaviours to a 
     * function, you make it harder to debug. For example, what happens to 
     * the linked list if you fail to read a character? That shouldn't be 
     * append's problem. 
     char c; 
     std::cout << "Please enter a single character: "; 
     std::cin >> c; 
     */ 
     node *current = new node(); 

     current->anything = c; 
     //std::cout << current->anything << std::endl; removed for same reason as above. 

     // think on this: how can head and tail NOT both be NULL at the same time? 
     // if you find a way, you have a bug that needs fixing. 
     if (head == nullptr && tail == nullptr) 
     { 
      // If head is NULL, it has no right_link to assign. This will fail horribly. 
      head->right_link = current; 
      tail->left_link = current; 
      current->left_link = head; 
      current->right_link = tail; 
      /* Consider instead 
      head = current; 
      tail = current; 
      */ 
     } 
     else 
     { 
      tail->right_link = current; 
      current->left_link = tail; 
      tail = current; 
      tail->right_link = nullptr; // don't need to do this. node constructor 
             // ensures current->right_link is NULL 
     } 
    } 
    // print function 
    void print() // no parameters required. head is ListManager member 
    { 
     node* temp; 
     temp = head; 
     // Again, if head is NULL, temp will be NULL and there will be no right_link 
     // consider instead 
     // while (temp != nullptr) 
     while (temp->right_link != nullptr) 
     { 
      std::cout << temp->anything << std::endl; 
      temp = temp->right_link; 
     } 
    } 
}; 

nodeが右ListManagerに組み込まれており、privateですか注意してください。 nodeにアクセスできるのはListManagerで、完全なアクセス権があります。

ListManagerには、追加されたnew edノードのすべてを処理するデストラクタも必要です。また、3のルールに準拠させるために、コピーコンストラクタと代入演算子が必要です。 "What is The Rule of Three?"お尋ねしますか?非常に重要です。将来のデバッグのためにリンクを読んでください。 3つのルールに従わないと、スタックオーバーフローに関するC++の質問が不規則になります。この統計をさらに膨らませることはできません。

使用法:

int main() 
{ 
    ListManager list; 
    char choice; 
    std::cout << "Please choose one menu option at a time:\n" << "1 = Append\n" 
      << "2 = Print list\n" << "3 = Exit\n\n"; 

    do 
    { 
     std::cout << "Menu option(1-3): "; 
     std::cin >> choice; 

     switch (choice) 
     { 
      case '1': 
       list.append('a'); // add to the end of list. 
       break; 
      case '2': 
       list.print(); // print list 
       break; 
      case '3': 
       std::cout << "end program\n\n"; 
       break; 
      default: 
       std::cout << "try again\n"; 
       break; 
     } 

    } while (choice != '3'); 

    return 0; 
} 
+0

ありがとうございました!これはとても役に立ちました。 –

0

まず第一に、頭と尾必要があります。ここに

void append(node *&head, node *&tail); 
void print(node *head); 


void append(node *&head, node *&tail) 
{ 
    char c; 
    cout << "Please enter a single character: "; 
    cin >> c; 
    node *current = new node(c); 
    cout << current->get_char() << endl; 
    if(head == NULL && tail == NULL) 
    { 
    head->setRightLink(current); 
    tail->setLeftLink(current); 
    current->setLeftLink(head); 
    current->setRightLink(tail); 
    } 
    else 
    { 
    tail->setRightLink(current); 
    current->setLeftLink(tail); 
    tail = current; 
    tail->setRightLink(NULL); 
    } 

} 
// print function 
void print(node *head) 
{ 
    node* temp; 
    temp = head; 
    while(temp->getRightLink()!=NULL){ 
    cout<<temp->get_char()<<endl; 
    temp = temp->getRightLink();  
    } 
} 

は私のメインであります最初に何もないので、NULLに初期化されます。

node *head = NULL; 
node *tail = NULL; 

次に、特に最初のif文を追加するようにコードを変更します。新しいリストを開始しているので

if(head == NULL && tail == NULL) 
{ 
    head = current; 
    tail = current; 
} 

にコードを変更 、頭と尾の両方を使用すると、挿入したばかりの同じノードです。

最後に、印刷機能でwhileループの条件を変更します。これほど簡単な何かが働くはずです。

現在のノードを印刷する場合は、右側のネイバーがなくても印刷します。

+0

ありがとう、それははるかに良い作品。 –

関連する問題