首页 > 解决方案 > 队列示例中的范围/可见性有困难的新 C++ 编码器

问题描述

全部,

上周我问了一个问题,我感谢您在回答时的宽容。我总体上是一个没有经验的编码员,但我一生中的大部分时间都在涉足。这是我上过的最难的语言/课程,它让我发疯,我无法理解其中的一些概念。我做了很多谷歌搜索,发现了一些有用的东西,但从来没有足够相似的东西来解决我遇到的问题。

另外:我对 SO 界面不太熟悉,所以上次不确定如何将答案“标记”为最好的,以表彰那些提供帮助的人。我没有看到回应其他较小评论的方法。这里有很多,但我想为你们花时间帮助他人的人做正确的事。

任务是创建一个包含五个文件的队列类,如下所述:

QueueItem.h包含 QueueItem 的类定义

QueueItem.cpp包含 QueueItem 的成员函数实现。

Queue.h包含 Queue 的类定义。

Queue.cpp包含 Queue 的成员函数实现。

main.cpp包含 main() 测试函数。

队列.h

#pragma once

#include "QueueItem.h"

class Queue {
public:
    Queue();    // ctor inits a new empty Queue
    ~Queue();   // dtor erases any remaining QueueItems
    void addItem(const char* pData);
    void removeItem();
    void print();
    void erase();

private:
    QueueItem* _pHead; // always points to first QueueItem in the list
    QueueItem* _pTail; // always points to the last QueueItem in the list
    int _itemCounter;  // always increasing for a unique id to assign to each new QueueItem
};

在下面的 Queue.cpp 中,有两个地方我认为代码应该是 _pTail->_pNext 或 _pTail._pNext。如果它是 ->,那么我得到C++ 成员(在第 21 行声明)不可访问,但使用 . 给出C++ 表达式必须具有类类型。这绝对是我认为这是我不理解的概念性事物的地方之一,因为我认为它应该是 -> 但不知道如何使其易于访问。

队列.cpp

#include "Queue.h"
#include "QueueItem.h"
#include <iostream>

using namespace std;

void Queue::addItem(const char* pData) {

    // dynamically create and init a new QueueItem object
    QueueItem* pItem = new QueueItem(pData, ++_itemCounter);

    if (0 == _pHead)  // check for empty queue
        _pHead = _pTail = pItem;

    else {
        // link new item onto tail of list using _pTail pointer
        _pTail->_pNext = pItem; // links the current pTail to the new pItem
        _pTail = pItem; // move the pTail to the new item
    }
}

void Queue::removeItem() {

    // check for empty queue
    if (0 == _pHead)
    { // if empty, nothing to do
    }
    else
    {
        // pop top item off
        QueueItem* popped = _pHead; // create popped to hold value of _pHead
        _pHead = popped->_pNext; // Move the pHead to the next in queue
        delete popped; // delete the popped value
        --_itemCounter; // decrement counter

    }
}

队列项.h

#pragma once

#include "Queue.h"



class QueueItem {
public:
    QueueItem(const char* pData, int id); // ctor
    void setNext(QueueItem* pItem);
    QueueItem* getNext() const;
    int getId() const;
    const char* getData() const;

private:
    char _data[30];    // data value (null terminated character string)
    const int _itemId; // unique id for item in queue
    QueueItem* _pNext; // next item in queue
};

在下面的 QueueItem.cpp 中,ctor 不正确。出现错误C++ 没有重载函数实例与指定类型匹配,我不知道为什么。看起来调用与定义匹配?

队列项.cpp

#include "QueueItem.h"
#include <cstring>
#include <string>

    QueueItem::QueueItem(char* pData, int id) // ctor
     : _itemId{ id } // Initialization list
{
     strcpy_s(_data, pData);
     _pNext = NULL;
}

void QueueItem::setNext(QueueItem* pItem)
{
     _pNext = pItem;
}
QueueItem* QueueItem::getNext() const
{
     return _pNext;
}
int QueueItem::getId() const
{
     return _itemId;
}
const char* QueueItem::getData() const
{
     return _data;
}

主文件

#include <iostream>
#include <conio.h>
#include "Queue.h"

using namespace std;


  // note - you may need to change the definition of the main function to 
  // be consistent with what your C++ compiler expects. 
int main() {

    char anykey;

    Queue myQueue;

    myQueue.removeItem();
    myQueue.addItem("red");
    myQueue.addItem("green");
    myQueue.addItem("blue");
    myQueue.addItem("orange");
    myQueue.print();  // print contents of queue (item ID and data)
    myQueue.removeItem();
    myQueue.removeItem();
    myQueue.removeItem();
    myQueue.removeItem();
    myQueue.print();
    myQueue.erase();
    myQueue.addItem("olive");
    myQueue.addItem("mauve");
    myQueue.addItem("purple");
    myQueue.print();
    myQueue.erase();
    myQueue.print();

    cout << "Press any key...";
    anykey = getch();
    return 0;
}

标签: c++

解决方案


让我们按顺序来看看。

  1. 队列.h

     #pragma once
    
     #include "QueueItem.h"
    

    您实际上并没有使用QueueItem此标头中的定义,您只提到了指向它的指针。要拥有一个指向类型的指针(无需取消引用它——即在标头中)——我们只需要知道该类型是否存在。

    因此,您可以将包含替换为前向声明

     class QueueItem;
    

    并打破两个头文件之间的循环。(您现在需要包含在内QueueItem.hQueue.cpp因为您确实在那里使用它)。

    您实际上不需要包含Queue.h其中QueueItem.h任何一个,因为它根本没有被使用。

  2. 在下面的 Queue.cpp 中,有两个地方我认为代码应该是_pTail->_pNext_pTail._pNext.

    是的,你的第一个想法是正确的。

    如果是->,那么我得到C++ member (declared at line 21 of) is inaccessible

    “无法访问”这个词告诉我们,问题_pTail->_pNext在于QueueItem::_pNext声明private。只有QueueItem类(或朋友)本身的方法才被允许访问其private成员。

    可以添加一个friend声明以QueueItem允许Queue对其私有部分具有特权访问权限。但是,由于您已经有一个public访问器,您可以_pTail->getNext()改为编写。

    但使用 . gives C++ expression must have class type.

    这是因为只有类(以及结构和联合)对象才有成员。你有一个指向类对象的指针,所以->是正确的选择。如果它有助于记住,p->member本质上与(*p).member...相同,只是打字更好。

  3. QueueItem.cpp下面,ctor 是不正确的。出现错误 C++ no instance of overloaded function matches the specified type,我不知道为什么。看起来调用与定义匹配?

    这两个不一样:

                QueueItem(const char* pData, int id);
     QueueItem::QueueItem(      char* pData, int id) { ... }
    

    我尝试尽可能地复制和粘贴这样的行 - 进行更多的打字没有任何好处,有更多的错误机会,当你知道你打算写什么时,有时很难看到这些简单的错误。


推荐阅读