链表私有指针C++



当指针处于"私有"状态时,我无法理解如何使用指针。

大多数情况下我不知道如何获取和设置指针的值

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

代码运行,但当我使用打印功能时它不执行任何操作。

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

这是我类的代码:

#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 = Appendn"
    << "2 = Print listn"
    << "3 = Exitnn";

    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 programnn";
                break;
            default: cout << "try againn";
                break;
        }

    }while(choice != '3');
return 0;
}
private成员

、指针或其他方式,是对象不希望被其他人弄乱或想知道是否有人弄乱的数据。

二传手和吸气手方法允许以受控方式访问private成员。例如,如果您有一个在任何情况下都不能大于 10 的私有整数,则可以在 setter 中使用代码来检查调用方是否试图强制值超出范围并拒绝请求。

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

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

这是物体的自卫。他们保持对谁将数据设置为什么的控制,并且可以保持一致性。假设您有一个更复杂的情况,在启用 FIR 滤波器的情况下,您无法以每秒超过 10000 个样本的速度对 A/D 进行采样,而不会使 CPU 不足并锁定系统。哎 呦。如果设置筛选器状态或采样率的唯一方法是通过 A/D 管理器对象中的资源库,则该对象可以测试、拒绝和防止灾难(并可能留下一条指向不良参与者的漂亮胖日志消息)。

在实现返回非常量引用或指针的 getter 之前,请仔细考虑。一旦调用方拥有其中之一,他们就可以对返回的数据做任何他们想做的事情。

经验法则是默认偏执:在没有充分理由的情况下不授予对任何数据的访问权限,然后更喜欢通过二传手和获取者进行受控访问。

关于您问题的具体情况。

链接节点的设置器和二传手通常是一个傻瓜赌注。节点很可能无法自行确定链接是否有效。只有列表管理员可以。在这种情况下,对象本身太无知而不知道什么是安全的,因此您必须向另一个知道更多的对象开放内部结构。 friend在这里很有用,尽管通常最好使节点的链接public并且永远不允许列表管理器将节点提供给客户端。

很有可能,客户应该对列表的工作原理一无所知。阅读有关耦合的信息。

所以节点应该是完全愚蠢的。这意味着你需要有一个ListManager类来(duh)管理列表并保护node免受行为不良的参与者的侵害。

ListManager包含您的headtailroot或其他任何内容以及appendremoveprint和其他列表管理方法。在任何情况下,这些函数中的任何一个都不会向调用方显示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 ed节点。它还需要一个复制构造函数和一个赋值运算符来使其符合三规则。"什么是三法则?"你问?这是非常重要的。阅读链接以节省将来的调试时间。不遵守三法则会导致堆栈溢出上不成比例的C++问题,进一步夸大这个统计数据是没有意义的。

用法:

int main()
{
    ListManager list;
    char choice;
    std::cout << "Please choose one menu option at a time:n" << "1 = Appendn"
            << "2 = Print listn" << "3 = Exitnn";
    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 programnn";
                break;
            default:
                std::cout << "try againn";
                break;
        }
    } while (choice != '3');
    return 0;
}

首先,头部和尾部应初始化为 NULL,因为开头什么都没有。

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

然后更改要追加的代码,尤其是第一个 if 语句。将代码更改为

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

由于您正在启动一个新列表,因此头和尾都是您刚刚插入的同一节点。

最后,在打印函数中更改 while 循环的条件。像这样简单的事情应该有效。

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

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

相关内容

  • 没有找到相关文章

最新更新