我想确保我理解这一点。
假设我有一个Animal类,我想制作一系列动物。
我可以举例来说
Animal animals[10];
这给了我一个动物数组,这样做时会调用默认的复制构造函数,现在我有10个空的Animal对象。
现在,如果我想开始"初始化"他们(我只知道java)我可以有像
这样的东西 for(int i=0; i<animals.length; i++){
animals[i] -> hasFur(true);
Animal -> incCount();
}
然后这会给我十个动物阵列都有毛皮,我会将动物计数器增加到10个。
当你说:
Animal animals[10];
初始化的值是什么?
答案 0 :(得分:3)
术语:
默认构造函数是一个可以不带参数调用的构造函数。例如:
class A { A() { /* ... */ } };
class Point { Point(int x = 0, int y = 0) { /* ... */ } };
复制构造函数是一个构造函数,其第一个参数的类型为X&
,const X&
,
volatile X&
或const volatile X&
,并且没有其他参数,或者所有其他参数都有默认参数&#34;。例如:
class A { A(const A& other) { /* ... */ } };
class Point { Point(Point& other, int x = 0) { /* ... */ } };
如果您的类声明没有构造函数,编译器将隐式定义默认构造函数。隐式定义的默认构造函数仅执行非常基本的初始化:
int
,double
,指针等执行初始化。)如果上述任何一个是不可能的(例如,类类型的成员没有默认构造函数),则编译器将报告错误。
如果您的类没有声明复制构造函数,则会隐式声明一个。如果声明了移动构造函数或移动赋值运算符,则将复制构造函数声明为已删除,并且任何使用它的尝试都将导致编译器错误。否则,隐式声明的复制构造函数将执行成员复制。
其次,与Java不同,C ++对象具有值语义。在Java中编写Animal animal;
时,animal
是引用到Animal
对象,并初始化为空引用。当您在C ++中编写Animal animal;
时,animal
是Animal
对象。当您在Java中编写Animal animal2 = animal;
时,animal2
和animal
引用相同的Animal
对象,并且您只是复制了引用。当您在C ++中编写Animal animal2 = animal;
时,animal2
是使用复制构造函数创建的animal
的副本。它们是不同的 Animal
对象。 (与此等效的Java是clone()
。)
此外,C ++和Java中的new
是非常不同的东西。在Java中,new
是创建对象的方式。在C ++中,如上所述,我们不需要new
来创建对象。相反,new
表示&#34;在堆上分配内存,在该内存中构造对象,并返回指向它的指针,当我和delete
时,我将使用new Animal()
释放该指针。完成&#34;。 Animal
没有返回Animal *
,它会返回Animal
- 指向animals[0] = new Animal();
的指针。因此,像new
这样的东西永远不会编译而没有一些可怕的hackery,即使你以某种方式使它编译,你已经丢失了delete
返回的指针,所以你不能Animal animals[10];
它,这意味着你现在有一个内存泄漏。它只是糟糕的C ++代码。不要这样做。
现在,当您在没有初始化程序的情况下在C ++中定义数组时:
Animal
您创建了一个包含10个Animal
对象的数组,而不是10个引用到Animal
个对象的数组。数组的每个成员都是默认构造的。如果Animal
未声明(显式或隐式)默认构造函数,则会出现编译器错误。执行的确切初始化取决于默认构造函数;如果你使用隐式的,那么标量类成员将具有不确定的值并尝试读取值未定义的行为。
确保默认构造的class Animal {
public:
Animal() : m_name("none"), m_legs(0) { }
private:
std::string m_name;
int m_legs;
};
没有未初始化成员的正确方法是简单地编写自己的默认构造函数来执行必要的初始化:
"none"
此默认构造函数将动物的名称初始化为字符串0
,将腿数初始化为std::array
。
C ++中的数组不带有它们的大小信息。有几种方法可以解决这个问题:
size()
类,它提供Animal animals[10];
成员函数,而不是普通数组。写std::array<Animal, 10> animals;
而不是animals.size()
。然后,您可以使用sizeof(animals) / sizeof(animals[0])
获取大小。这是迄今为止最好的方式。animals
计算数组的大小。如果你将sizeof
传递给另一个函数(除非函数以非常特殊的方式编写),这将无法工作,因为数组将在一滴帽子处衰减到指针,并在一个函数上调用const int szAnimals = 10; Animal animals[szAnimals];
指针不会给你数组的大小。答案 1 :(得分:1)
以下示例代码将执行您要查找的内容(当最初根据下面定义的默认构造函数定义数组时,hasFur默认为false);但是,您不清楚提到incCount()
例程的请求是什么。请注意,std::array
和std:vector
都没有length
方法,而是使用size
(std::array
std::vector
)完成
#include <array>
#include <iostream>
using namespace std;
class Animal
{
private:
bool __hasFur;
public:
Animal(bool hasFur = false)
{
this->__hasFur = hasFur;
}
void hasFur(bool hasFur)
{
this->__hasFur = hasFur;
}
};
int main (int argc, char ** argv)
{
array<Animal, 10> animals;
for(size_t i = 0; i < animals.size(); i++)
{
animals[i].hasFur(true);
//Animal.incCount();
}
return 0;
}
incCount()
方法的目的是什么?
答案 2 :(得分:1)
C ++ 不对数组具有关联的length
属性。 (见How do I find the length of an array?)
您可以这样做:
int length = sizeof(animals)/sizeof(animals[0]);
然后,在访问元素的成员变量之前(例如: animals[i] -> hasFur(true);
),您需要先创建对象。
animals[i] = new Animal(); // assuming the constructor has no arguments
击> <击> 撞击> [编辑:不一定,请参阅this answer]
另外,Amimal -> incCount()
给我看起来不错。您可以在构造函数中递增计数器。这样可以确保您不会意外地调用incCount()
并弄乱静态变量的计数。
答案 3 :(得分:0)
我不认为你可以用C ++做animals.length(),我认为你的&#34; for&#34;需要是这样的:
for(int i=0; i<=10; i++){
animals[i].hasFur(true);
Animal.incCount();
}
关于Animal数组初始化的内容:它取决于类构造函数。默认构造函数只是创建对象但不为变量赋值,因此除非您声明了自定义构造函数,否则对象的变量将设置为随机值。