好的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)中的'operator ='不匹配 - > PolyGon :: aArray =(((PointArray *)operator new(8u)),( - > PointArray :: PointArray(( (const Point *)point),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];
}
}
好的,在我提交之前,我找到了一个答案,说明如果对象没有默认构造函数,则必须使用初始化列表初始化它。我现在有三个问题:
我的无参数构造函数如下所示:
PointArray(){size = 0; x = new Point[0];}
答案 0 :(得分: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);
如果这是在代码块(局部变量;技术上,在块范围)内,那么当程序离开该块时它将被自动销毁。如果它不在任何函数内(全局变量;技术上,在命名空间范围),那么它会持续一段时间(或多或少);但全局通常被认为是一个坏主意。
我有一个no-arg构造函数。那么为什么它会给我这个错误呢?
正在使用默认构造函数;但是你试着给它指定一个指针。如果你真的想避开初始化列表(你不应该这样做),那么你可以通过复制临时名称来重新分配它:
PolyGon(Point point[], const int newSize) {
aArray = PointArray(point, newSize); // No new
}
但这可能效率较低,并要求该类型实现它可能不需要的默认构造函数和复制赋值运算符。还有一些类型(例如常量和引用)不能默认初始化或重新分配。列表中的直接初始化适用于所有类型。
答案 1 :(得分:2)
PolyGon(Point point[], const int newSize) : aArray(point, newSize){}
这说“作为构建PolyGon对象的第一部分,使用参数aArray
构建它的内部point, newSize
。我在这里故意使用”内部“这个词。为了使它更清楚,我我将使用“人”对象作为类比。在Java中,对象彼此引用。在创建一个新的人对象时,你创建一个新的(单独的)名称对象,然后告诉该人他们现在拥有这个名字。
在C ++中,它甚至不能像那样远程工作。成员(皮肤和血液)实际上是对象本身的一部分。当制作一个人物时,你必须同时制作皮肤物体和血液物体,当你制造这个人时,你不能单独制造它们然后告诉那个人他们现在拥有那个皮肤。同样,你不能在不破坏这个人的情况下将它们移除或摧毁它们。构造函数体是活着(出生)的过程。
这解释了为什么必须在构造函数体开始之前构造成员(人不能开始“生活”直到皮肤完成),以及为什么你不能给成员一个new
对象(可以' t带走一个人的皮肤并给他们另一个)该成员字面该对象的一部分。初始化列表构造对象的成员,它们是字面上对象的一部分,并且对象需要“生存”。 (人类比喻在子宫里正在增长)一旦部件组装好并准备就绪,那么构造体最终开始,这开始使对象最终“活着”(出生)。
从C ++ 11规范,第3.8 / 1节§ 类型T的对象的生命周期从...初始化完成时开始。当析构函数调用开始时,类型T的对象的生命周期结束。
所以我完全没有弥补“生命”的termononlogy。
回到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
答案 2 :(得分:0)
aArray(point,newSize)相当于aArray = new PointArray(point,newSize)。
没有
PointArray aArray;
aArray
类型为PointArray
,但不是PointArray *
。两者都是C ++中的不同类型。因此,当您尝试将PointArray *
分配给成员变量aArray
时,会出现编译错误。