【问题标题】:Copy Constructor Error With a Template Linked List Class使用模板链接列表类复制构造函数错误
【发布时间】:2015-04-13 10:23:39
【问题描述】:

我正在使用模板类对链表进行分配。

在我的 main.cpp 中,我应该能够创建列表(有效)并使用赋值运算符或复制构造函数创建另一个列表。这是我的代码:

template <class T>
LinkedList<T>::LinkedList(const LinkedList<T>& other)
{
    Node<T>* tmp = other.getLeader(); //LINE WHERE THE ERROR OCCURS

    for(int i = 0; tmp != NULL; i++)
    {
        insert(i, tmp->element);
        tmp = tmp->next;
    }
}

template <class T>
Node<T>* LinkedList<T>::getLeader()
{
    return head;
}

错误显示:

linkedList.C:61:6: error: passing ‘const LinkedList<int>’ as ‘this’ argument 
    of ‘Node<T>* LinkedList<T>::getLeader() [with T = int]’ 
    discards qualifiers [-fpermissive] tmp = other.getLeader();

Main.cpp:

int main()
{
    LinkedList<int> list;
    list.insert(0, 0);
    list.insert(1, 1);
    list.insert(2, 2);
    cout << list;

    LinkedList<int> list2(list);
    cout << list2;

    return 0;
}

element 和 next 是 Node 类的公共变量。

请注意,由于这项任务的性质,我不能只更改类定义,只更改类的实现。

编辑:

template <class T>
LinkedList<T>::LinkedList(const LinkedList<T>& other) // I CANNOT CHANGE THIS
{
    // I CAN CHANGE THIS
}

【问题讨论】:

  • 您是否使用new 在插入中进行深层复制?你默认headnullptr 吗?编辑:这与您的编译器错误无关,只是我自己的熏陶。
  • 您的错误是因为getLeader() 不是常量。修复它。
  • 旁注——我赞赏在您的复制构造函数中,您没有在 insert 函数中重新实现代码,而是重用了它。太多的新手犯了在他们的复制构造函数中重写整个insert 功能的错误。

标签: c++ copy-constructor singly-linked-list


【解决方案1】:

问题是您尝试为 const 对象 other 调用非常量成员函数 LinkedList&lt;T&gt;::getLeader()

由于getLeader成员函数不会修改对象,所以可以设为const:

template <class T>
Node<T>* LinkedList<T>::getLeader() const

另外,如果你还想防止调用者无意中修改返回的节点,也将返回类型设为 const :

template <class T>
const Node<T>* LinkedList<T>::getLeader() const

在这种情况下,您必须相应地调整tmp 的定义。

如果您无法使用getLeader 签名解决上述问题(如您对问题的编辑所示),您可以选择以下选项(按优先顺序排列):

  • 使用 LinkedList 类的其他功能,这些功能可以用于 const 对象(例如迭代器),前提是此类功能可用
  • 直接访问otherhead 数据成员,而不是使用getLeader 成员函数
  • 在调用getLeader 之前,使用const_cast 抛弃other 的常量性

【讨论】:

  • 由于我无法按照您所说的更改函数(.h 文件将在标记过程中被替换),是否有另一种方法可以实现复制构造函数而无需向函数添加内容姓名?感谢回复
  • 我不明白你如何修改构造函数,而不是另一个成员函数。但是假设你有你的理由,那么你将不得不使 other 对象非 const (或者通过定义构造函数参数,或者通过抛弃 const-ness)。但更喜欢我的答案中提出的解决方案。
  • 我也喜欢你的方法。让我指出我可以改变什么,什么不能改变。请查看问题中的编辑
  • 感谢您的帮助,但我决定只使用成员变量而不使用 getLeader 函数。似乎是这样工作的。也许这就是讲师希望我们首先做的事情。
  • @Ravenblack : 这是我编辑中的第二个选项 ;) 很高兴你能正常工作。
【解决方案2】:

getLeader() 的签名更改为const 确实是解决您的问题的“好”解决方案(并且,为了遵守许多其他情况下使用的标准,它可能应该被命名为head().. .),但是考虑到您可以控制类本身,还有另一种方法可以解决您的问题。

由于您是在类中执行此操作,因此您也可以访问私有成员 - 其中包括同一类的其他实例的私有成员。如果你看看getLeader() 做了什么,它可能是这样的1

template<typename T>
class LinkedList {
private:
    Node<T>* head;

public:
    const Node<T>* getLeader() {
        return head;
    }
}

这意味着在您的复制构造函数/赋值运算符中,您可以直接访问other.head,而不是通过getLeader()。只要您不尝试更改other.head 的值,就可以了。


1) 注意:未经测试。我把它写在我的脑海里,所以它甚至可能无法编译。我希望我的观点即使没有编译也能被理解......

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-03-22
    • 1970-01-01
    • 2021-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多