访问类成员指针

时间:2013-09-18 17:07:47

标签: c++

假设我有List和Node的以下定义:


template <class T> 
class List {
    public:
        class Iterator;
        class ConstIterator;

        //Constructors and Destructors.
        List() : head(NULL), tail(NULL), size(0) {}
        List(const List& list);
        ~List();

        //Methods
        Iterator begin();
        ConstIterator begin() const;
        Iterator end();
        ConstIterator end() const;
        void insert(const T& data);
        void insert(const T& data, const Iterator& iterator);
        void remove(const Iterator& iterator);
        int getSize() const;
        Iterator find(const T& item);
        ConstIterator find(const T& item) const;
        void sort();

        //Operators
        List operator = (const List& list);


    private:
        class Node;
        Node* head;
        Node* tail;
        int size;
};


template <class T>
class List<T>::Node
{
    public:
        //Constructors and destructors
        Node(const T& _data, const Node* _next) : data(_data), next(_next) {}       
        ~Node(); //Destructor 

        //Methods


        //Operators
        Node operator = (const Node& node);

    private:
        T data;
        Node* next;
};

我正在编写一个函数来将数据插入到这样的列表中:


    template<class T>
    void List<T>::insert(const T& data)
    {
    Node newNode = new Node(data, NULL);

    if (head == NULL)
    {
        head = &newNode;
        tail = &newNode;
    }
    else
    {
        (*tail)->next = &newNode;
        tail = &newNode;
    }
    size++;
}

然而,我发现奇怪的是,如果我将(*tail)->next = &newNode;交换为(*tail).next = &newNode;,它仍会编译。为什么,这样做的正确方法是什么?

4 个答案:

答案 0 :(得分:1)

您的类的定义可以(为了本问题的目的)简化为:

class List {
    ...
    private:
        Node* head;
        Node* tail;
};

class Node {
    ...
    private:
        Node* next;
};

现在使用List::insert方法:

Node newNode = new Node(data, NULL);
(*tail)->next = &newNode;

...当你使用new表达式时,结果将是指向新分配的内存的指针 你应该做的是:

Node* newNode = new Node(data, NULL);
tail->next = newNode;                // <-- equivalent to (*tail).next = newNode;

答案 1 :(得分:0)

- &gt;运算符将自动为您指向一个指针,然后向右调用该方法。所以:

tail->next

也可以,但

tail.next

不会因为tail是一个指针。要使用。运算符你必须首先在

中去除指针
(*tail).next

(*tail)

将指针变为对象。那时你可以使用 - &gt;要么 。

A。不会对指针起作用但是 - &gt;将

一般来说,为了便于打字,我使用了 - &gt;因为它比使用(*)将指针转换为对象更短,所以我可以使用点,但它们是等效的操作。

答案 2 :(得分:0)

使用Node-&gt; tail是写入的简短形式(* Node).tail。两种形式都有效。 Strangeus是你说(* Node) - &gt;尾部编译的事实。为此,必须将Node定义为双指针,即:

Node **tail;

但是你的代码还有其他一些错误。在这一行中:

Node newNode = new Node(data, NULL);

您定义了一个本地对象并为其分配动态内存。正确的方法是:

Node *newNode = new Node(data, NULL);  // defining it as a pointer

而不是作为:

head = &newNode;

做的:

head = newNode;

作为最后一点,请考虑使用智能指针而不是原始指针。前者比上一个更安全

答案 3 :(得分:0)

您已注意到(*tail)->next = &newNode(*tail).next = &newNode都编译,这会让您感到奇怪。

但不知何故,你可能也注意到这条线也会编译!

Node newNode = new Node(data, NULL);

是你应该暂停的事情。

你在这里的模板里面。很多东西“编译”。

您是否尝试过实例化模板?

附录:

这里只是为了告诉你有多疯狂,看一下这个程序:

#include <iostream>
using namespace std;

template <class T>
class C {
  void f();
};

template <class T>
void C<T>::f() {
  int x = new int;
}

int main() {
  std::cout << "Hello, world\n";
}

现在看看这个:

$ g++ template-example.cpp && ./a.out 
Hello, world

但现在注意

#include <iostream>
using namespace std;
int main() {
  int x = new int;
  std::cout << "Hello, world\n";
}

产生:

$ g++ hello.cpp
hello.cpp: In function ‘int main()’:
hello.cpp:4: error: invalid conversion from ‘int*’ to ‘int’

TL; DR:当你在某个模板中时,那些不应该编写“DO”的东西!(他们并没有真正编译 - 是的!)