0

好的 C++ 新手,我非常了解 Java,现在正在尝试学习 C++。无论如何,这是我的简单课程。

class PolyGon{

    private:
        PointArray aArray;
        static int numberOfInst;

    public:
        PolyGon(Point point[], const int newSize) : aArray(point, newSize){} 
};

这很好。如果我错了,请纠正我,但在初始化列表aArray(point, newSize)中相当于aArray = new PointArray(point, newSize).

因为当我尝试完全相同的代码但将最后一行更改为:

class PolyGon{

    private:
        PointArray aArray;
        static int numberOfInst;

    public:
        PolyGon(Point point[], const int newSize){aArray = new PointArray(point, newSize)} 
};

这给出了例外:

'((PolyGon*)this)->PolyGon::aArray = (((PointArray*)operator new(8u)), (->PointArray::PointArray(((const Point*)) 中的 'operator=' 不匹配点), newSize), ))'|

如果您想在这里查看 PointArray 的构造函数,它是:

PointArray::PointArray(const Point points[], const int newSize)
{
    size = newSize;

    x = new Point[size];

    for(int i = 0; i < size; i++)
    {
        x[i] = points[i];
    }
}

好的,在我提交之前,我找到了一个答案,如果对象没有默认构造函数,则必须使用初始化器列表对其进行初始化。我现在有三个问题:

  1. 为什么是这样?为什么我不能按照我想要的方式去做。
  2. 此规则是否仅适用于构造函数。就像我可以说“PointArray aArray = new PointArray(point, newSize);” 别的地方?
  3. 我确实有一个无参数构造函数。那么为什么它给我这个错误呢?

我的无参数构造函数如下所示:

PointArray(){size = 0; x = new Point[0];}
4

3 回答 3

3

为什么是这样?为什么我不能按照我想要的方式去做。

在 Java 中,aArray将是对您必须使用创建的单独对象的引用new

在 C++ 中,你必须忘记你所知道的关于 Java 对象模型的一切。aArray是包含在 中的对象PolyGon,在创建时自动PolyGon创建,并在构造函数主体运行之前初始化。如果您需要提供构造函数参数,则必须在构造函数主体之前的初始化列表中给出这些参数;当你进入构造函数体时,它已经被初始化了。

此规则是否仅适用于构造函数。就像我可以在PointArray aArray = new PointArray(point, newSize);别的地方说吗?

new返回指向动态对象的指针;所以你可以用它来初始化一个指针(不是一个对象):

// Careful! This is a recipe for memory leaks.
PointArray * aArray = new PointArray(point, newSize);

但请记住,如果你用 创造了一些东西new,你必须delete在用完后将其销毁。没有垃圾回收,所以废弃的动态对象会泄漏内存。为防止这种情况,new请尽可能避免,并学习如何在您确实需要动态资源时使用RAII来管理它们。

您也可以在没有以下情况下创建对象new

PointArray aArray(point, newSize);

如果这是在代码块内(一个局部变量;从技术上讲,在块范围内),那么当程序离开该块时它将自动销毁。如果它不在任何函数内(全局变量;从技术上讲,在命名空间范围内),那么它会在程序的持续时间内持续(或多或少);但是全局变量通常被认为是一个坏主意。

我确实有一个无参数构造函数。那么为什么它给我这个错误呢?

正在使用默认构造函数;但随后您尝试为其分配一个指针。如果你真的想避免初始化列表(你不应该这样做),那么你可以通过复制一个临时的来重新分配它:

PolyGon(Point point[], const int newSize) {
    aArray = PointArray(point, newSize);  // No new
} 

但这可能效率较低,并且要求该类型实现它可能不需要的默认构造函数和复制赋值运算符。还有一些类型(例如常量和引用)不能被默认初始化或重新分配。列表中的直接初始化适用于所有类型。

于 2013-08-16T18:36:16.177 回答
2
PolyGon(Point point[], const int newSize) : aArray(point, newSize){} 

这表示“作为构造 PolyGon 对象的第一部分,aArray使用参数构造它是内部的point, newSize。我在这里故意使用“内部”一词。为了更清楚,我将使用“人”对象作为类比。在 Java 中,对象相互引用。当创建一个新的人对象时,你创建一个新的(单独的)名称对象,然后告诉这个人他们现在拥有这个名字。

在 C++ 中,它甚至不能像那样远程工作。成员(皮肤和血液)实际上是对象本身的一部分。制作人物对象时,必须同时制作皮肤对象和血液对象,在制作人物时,不能分别制作,然后告诉人他们现在拥有该皮肤。同样,你不能在不摧毁人的情况下移除它们或摧毁它们。构造函数体是变得有生命(被出生)的过程。

这解释了为什么必须在构造函数体开始之前构造成员(在皮肤完成之前,人不能开始“生活”),以及为什么你不能给成员一个new对象(不能拿走一个人的皮肤并给予他们另一个)成员实际上是对象的一部分。初始化器列表构造对象的成员,这些成员实际上是对象的一部分,并且是对象“存活”所必需的。(人的比喻是在子宫里成长) 一旦零件组装好并准备就绪,那么构造器主体终于开始了,它开始了使对象最终“活着”(出生)的过程。

从 C++11 规范第 3.8/1 节
开始,类型 T 的对象的生命周期开始于...其初始化完成。T 类型对象的生命周期在......析构函数调用开始时结束。

所以我完全没有编造“生活”的术语。

回到 C++ 代码:

PolyGon(Point point[], const int newSize) 
//when making a new PolyGon
: aArray(point, newSize)
//construct it's internal aArray member at the same time
{}
//No additional steps needed to make it "live".

关于new关键字: Java
new任何东西都需要关键字,因为Java无论如何都将所有对象分开存储,所以你随便使用new。在 C++ 中,我们可以在其他对象内部或堆栈内存中创建对象。我们不需要系统为我们创建new对象,我们需要在我们已有的空间中构建对象。或者,如果您绝对需要一个单独的或动态的对象,您可以使用new在堆中创建一个新对象。

{
    PolyGon inst; //this construts a PolyGon object _in_ the stack space
                 //we refer to this object by the name "inst"
    inst.print_name(); //work with inst directly
    PolyGon* ptr = new PolyGon(); //this constructs a brand new PolyGon _in_ the "heap"
                                  //and a pointer _in_ the stack space
                                  //and stores the position of the PolyGon in the pointer
                                  //we refer to this _pointer_ by the name "ptr"
    ptr->print_name(); //call print_name on the object that ptr points at.
    delete ptr; //delete the thing that ptr points at
    ptr = &inst;  //now we store the address of inst in the ptr pointer object
    ptr->print_name(); //call print_name on inst
} //inst was in the stack, so as the stack unwinds, "inst" is destructed automatically
  //ptr also destructed. Destructing pointers DOES NOT destroy the things they point at
于 2013-08-16T18:02:19.943 回答
0

aArray(point, newSize) 等价于 aArray = new PointArray(point, newSize)。

不。

PointArray aArray;

aArray类型是PointArray但不是PointArray *。两者都是 C++ 中的不同类型。因此,当您尝试分配PointArray *给成员变量时会出现编译错误aArray

于 2013-08-16T17:45:07.740 回答