【问题标题】:New C++ Template class Constructor that takes a type of itself as an argument将自身类型作为参数的新 C++ 模板类构造函数
【发布时间】:2012-08-10 02:29:40
【问题描述】:

我正在用 C++ 编写一个类似于 java 中的 ArrayList 的模板类(是的,我知道 vector 做同样的事情,这不是一个实用的编码项目)。

我认为为我的 ArrayList 类提供一个构造函数会很有用,它接受另一个 ArrayList 作为参数来为 ArrayList 播种。但是当我尝试编写构造函数时,我得到了这个错误

invalid constructor; you probably meant 'ArrayList<T> (const ArrayList<T>&)'

这是否意味着 ArrayList 必须是一个常数?为什么我需要 addressof 操作符?

我仍在学习 C++,所以我有点困惑。

原型在这里:

    ArrayList(ArrayList<T> list);
    ArrayList(ArrayList<T> list, int size);

代码在这里:

/**
 * Creates an ArrayList of type T that is twice the
 * size of the passed in ArrayList, and adds all elements
 * from the passed ArrayList<T> list, to this ArrayList.
 *
 * Runs in O(n) time, where n = the size of list.
 *
 * @param list the ArrayList to use as a seed for this ArrayList.
 */
template<class T>
ArrayList<T>::ArrayList(ArrayList<T> list) {

    array = new T[list.getSize() * 2];
    capacity = list->getSize() * 2;
    size = list->getSize();

    for (int i = 0; i < list->getSize(); i++) {

        array[i] = list->get(i);
    }
}

编辑 下面的代码没有错误,而上面的则......

/**
 * Creates an ArrayList of type T that has a capacity equal to the passed
 * in theCapacity parameter. This ArrayList starts with the passed ArrayList.
 *
 * Note: If the passed in capacity is smaller than the size of the passed in
 *          ArrayList, then the capacity is set to twice the size of the
 *          passed ArrayList.
 *
 * @param list the ArrayList to use as a seed for this ArrayList.
 * @param theCapacity the capacity for this ArrayList.
 */
template<class T>
ArrayList<T>::ArrayList(ArrayList<T> list, int theCapacity) {

    if (theCapacity >= list->getSize()) {

        array = new T[theCapacity];
        capacity = theCapacity;
    }
    else {

        array = new T[list->getSize() * 2];
        capacity = list->getSize() * 2;
    }

    size = list->size;

    for (int i = 0; i < size; i++) {

        array[i] = list->get(i);
    }
}

【问题讨论】:

标签: c++ templates constructor


【解决方案1】:

使用

 ArrayList<T>::ArrayList(const ArrayList<T>& list)

作为您的构造函数签名,将数组列表作为const 引用传递。这是复制构造函数的正确签名。实现和调用代码都不需要更改,除非您在 ctor 中修改 list

当您执行ArrayList&lt;T&gt;::ArrayList(ArrayList&lt;T&gt; list) 时,您正在创建整个 ArrayList 实例的临时副本。 (您不能对 ctor 执行此操作,因为它会调用无限递归,因为 list 的新副本将使用相同的函数定义等等)。

ArrayList&lt;T&gt;::ArrayList(ArrayList&lt;T&gt;&amp; list) 将列表作为引用传递,这意味着它不再是通常所说的“按值传递”,而是根据调用代码处理列表的确切版本。

通过在函数中接受 const 引用,您表示该函数不会修改引用的内容(即不对它进行任何修改操作:它将被限制为仅const 访问)。在继续之前,您应该阅读有关 const、引用和复制构造函数的内容。

更新:

对于按值或引用传递,您可以通过obj.member 语法访问成员。如果您要传递像ArrayList&lt;T&gt;::ArrayList(ArrayList&lt;T&gt;* list) 这样的指针,则必须使用list-&gt;member 语法或(*list).member 语法,更不用说首先检查列表是否为0/nullptr(您不能取消引用空指针) .

您正在混合使用指针语法和值/引用语法。将所有list-&gt;x 转换为list.x,因为您没有使用指针传递list 参数。

查看不同的传递行为:http://ideone.com/3c5mJ

【讨论】:

  • 当我切换到那个时,虽然我在'->'的构造函数基本操作数的内容上收到此错误,但如果我使用 addressof怎么可能是非指针类型?! :?
  • @Ethan 现在它是一个引用,您可以像传递值一样使用obj.member 语法。这就是引用在 C++ 中的工作方式。
  • 这意味着您的功能实现有问题。您需要向我们提供更多详细信息,您如何实现该类并使用它。
  • 我的所有函数都有测试代码,它们在那里运行良好,所以我认为问题不在于我的函数。这也很奇怪....在其中一个构造函数中,我已经有了 -> 运算符并且我没有收到任何错误(但是如果我切换到简单的 obj.memberFunction() 语法,我会收到一个错误:无效参数' 候选人是: int getSize() ' 而在另一个构造函数上,我使用 -> 运算符得到非指针类型错误,并且使用 .functionMember() 语法我得到与上面相同的错误......我是如此丢失
【解决方案2】:

使用“const”是因为它是某个对象的引用,您不会更改它。 使用引用是因为这是复制构造函数,默认语法假设引用。

但最重要的是:您可以按照与您尝试编写的方式完全相同的方式定义和使用此构造函数。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-06-01
    • 2021-11-02
    • 1970-01-01
    • 2015-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多