Linked List私有指针C ++

时间:2016-07-06 22:09:43

标签: c++ class pointers linked-list private

我无法理解如何在" private"中使用指针。

主要是我不知道如何获取和设置指针值

我想创建一个没有字符值的头尾节点。 然后创建位于头部和尾部之间的新节点,并将新节点添加到列表的末尾(尾部之前)。

代码运行,但在使用打印功能时它没有做任何事情。

抱歉,如果我的格式错误且代码太长。

这是我班级的代码:

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

这是我的功能:

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

这是我的主要内容:

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

2 个答案:

答案 0 :(得分:0)

首先,head和tail应初始化为NULL,因为开头没有任何内容。

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

然后更改您的代码以追加,特别是第一个if语句。 将您的代码更改为

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

由于您要开始一个新列表,head和tail都是您刚刚插入的节点。

最后在打印功能中更改while循环的条件。像这样简单的东西应该有效。

while (temp) {
    cout << temp->get_char() << endl;
    temp = temp->getRightLink();
}

您想要打印当前节点,即使它没有正确的邻居。

答案 1 :(得分:0)

private成员,指针或其他,是对象要么不希望被其他人弄乱或者想要知道是否有人与他们混淆的数据。

Setter和getter方法允许以受控方式访问private成员。例如,如果您有一个私有整数,在任何情况下都不能超过10,您可以在setter中设置代码,以检查调用者是否试图强制该值超出范围并拒绝该请求。

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

现在程序不会有任何令人讨厌的惊喜,X == 11导致超出范围的访问或其他。

这是对象的自卫。他们可以控制谁将数据设置为什么,并保持一致性。假设你有一个更复杂的情况,你不能在每秒超过10000个样本的情况下采样A / D,同时启用FIR滤波器而不会使CPU瘫痪并锁定系统。哎呦。如果设置过滤器状态或采样率的唯一方法是通过A / D管理器对象中的设置器,则该对象可以测试并拒绝并防止灾难(并且可能留下指向坏人的好的胖日志消息)。

在实现返回非常量引用或指针的getter之前要非常认真。一旦调用者具有任何一个,他们就可以对返回的数据做任何他们想做的事。

经验法则是默认为偏执狂:没有充分理由不允许访问任何数据,然后更喜欢通过setter和getter进行受控访问。

根据您问题的具体情况。

链接节点的getter和setter通常是一个糟糕的赌注。如果链接有效,节点很可能无法自行确定。只有列表管理员才可以。这种情况下,对象本身太无知,无法知道什么是安全的,所以你必须打开另一个知道更多的对象的内部。 friend在这里很有用,但通常最好是创建节点的链接public,并且永远不允许列表管理器将节点提供给客户端。

赔率很高,客户应该完全不了解列表的工作方式。阅读耦合。

所以节点应该是完全愚蠢的。这意味着您需要有一个ListManager类来管理列表并保护node不受行为不端的演员的影响。

ListManager包含headtailrootappendremoveprint等其他内容列表管理方法。在任何情况下,这些函数都不会向调用者显示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的方式是ListManager。现在只有node才能访问ListManager并且具有完全访问权限。

delete还需要一个析构函数来处理new所有附加的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; } 个ed节点。它还需要一个复制构造函数和赋值运算符,以使其符合Rule of Three。 “What is The Rule of Three?”你问?这非常重要。阅读链接以节省未来的调试时间。不遵守三规则会导致Stack Overflow上的C ++问题数量不成比例,并且没有必要进一步夸大这一统计数据。

用法:

filterNot