C++ 和 Java 中的动态对象数组有何不同?
how arrays of dynamic objects differs in C++ & Java?
我最近在 Java 中了解了对象数组。
考虑一下:
Student s[]=new student[3];
但是为什么上面的语句只创建了一个可以保存对 3 个学生对象的引用的数组。它不会自己创建学生 class 对象。我必须使用 Student class 的构造函数单独创建它们。所以如果我尝试像这样访问任何 class 成员:
s[0].name="meet"
会产生运行时错误"NullPointerException"
但这些对我来说似乎很奇怪,因为在 C++ 中这些不是必需的。
考虑这个 C++ 程序。
#include <iostream>
using std::cout;
class Test
{
public:
Test()
{
cout<<"Constructor\n";
}
void fun()
{
cout<<"fun() is called\n";
}
~Test()
{
cout<<"Destructor\n";
}
};
int main()
{
Test* t=new Test[3];
for(int i=0;i<3;i++)
t[i].fun();
delete[] t;
return 0;
}
当 main() 中的第一个语句执行时内部会发生什么?如果它在 C++ 中工作正常那么为什么在 java.
中生成 NullPointerException
class test
{
test()
{
System.out.println("Constructor");
}
void fun()
{
System.out.println("fun() is called");
}
public static void main(String args[])
{
test t[]=new test[3];
for(int i=0;i<3;i++)
t[i].fun(); // oops runtime error
for(int i=0;i<3;i++)
t[i]=new test();
for(int i=0;i<3;i++)
t[i].fun(); // now fine.
}
}
为什么在java中必须使用class的构造函数单独创建对象,而在C++中却不需要使用class的构造函数单独创建?
请帮助我。
简短的回答只是因为语法(几乎相同)并不意味着它的工作原理相同。实际上,由于 Student s[]
中的 [],您编写的语句不会在 C++ 中编译
与您的 Java 代码等效的 C++ 代码是:
Student** s = new Student*[3];
然后您可以像这样初始化学生:
s[0] = 新学生("Jimmy");
这是一个需要掌握的重要概念,因为 Java 并不是唯一以这种方式不同于 C++ 的编程语言。
这是一个完整的示例,您可以尝试一下。使用 g++ 4.3.2
编译
#include <iostream>
#include <string>
class Student {
public:
Student() : name_("<unknown>") {
std::cout << "Default constructor called" << std::endl;
}
Student(const char* name) : name_(name) {
std::cout << "constructor called with name '" << name << "'" << std::endl;
}
void setName(const std::string& name) { name_ = name; }
const std::string& getName() const { return name_; }
private:
std::string name_;
};
void demoArrayOfValues() {
std::cout << "demoArrayOfValues()" << std::endl;
// Here the default constructor will be called 3 times because
// creating you're creating an array of objects
Student* s = new Student[3];
for (int x = 0; x < 3; ++x) {
std::cout << "Student[" << x << "] (byValue): " << s[x].getName() << std::endl;
}
s[0].setName("Jimmy");
s[1].setName("Sally");
s[2].setName("Susie");
for (int x = 0; x < 3; ++x) {
std::cout << "Student[" << x << "] (after setting): " << s[x].getName() << std::endl;
}
std::cout << std::endl;
}
void demoArrayOfPointers() {
std::cout << "demoArrayOfPointers()" << std::endl;
// This is the C++ equivalent of the Java example that started the question
// Here you're creating an array of pointers and have to create the objects
// themselves
Student** s = new Student*[3];
for (int x = 0; x < 3; ++x) {
std::cout << "Student[" << x << "] (pointer): " << s[x] << std::endl;
}
s[0] = new Student("Jimmy");
s[1] = new Student("Sally");
s[2] = new Student("Susie");
for (int x = 0; x < 3; ++x) {
std::cout << "Student[" << x << "] (after creating): " << s[x]->getName() << std::endl;
}
std::cout << std::endl;
// Now we iterate over the elements in the array and delete each one.
for (int x = 0; x < 3; ++x) {
delete s[x];
}
// Now we delete the array itself
delete [] s;
}
int main(int argc, const char** argv) {
demoArrayOfValues();
demoArrayOfPointers();
return 0;
}
我最近在 Java 中了解了对象数组。 考虑一下:
Student s[]=new student[3];
但是为什么上面的语句只创建了一个可以保存对 3 个学生对象的引用的数组。它不会自己创建学生 class 对象。我必须使用 Student class 的构造函数单独创建它们。所以如果我尝试像这样访问任何 class 成员:
s[0].name="meet"
会产生运行时错误"NullPointerException"
但这些对我来说似乎很奇怪,因为在 C++ 中这些不是必需的。 考虑这个 C++ 程序。
#include <iostream>
using std::cout;
class Test
{
public:
Test()
{
cout<<"Constructor\n";
}
void fun()
{
cout<<"fun() is called\n";
}
~Test()
{
cout<<"Destructor\n";
}
};
int main()
{
Test* t=new Test[3];
for(int i=0;i<3;i++)
t[i].fun();
delete[] t;
return 0;
}
当 main() 中的第一个语句执行时内部会发生什么?如果它在 C++ 中工作正常那么为什么在 java.
中生成 NullPointerException class test
{
test()
{
System.out.println("Constructor");
}
void fun()
{
System.out.println("fun() is called");
}
public static void main(String args[])
{
test t[]=new test[3];
for(int i=0;i<3;i++)
t[i].fun(); // oops runtime error
for(int i=0;i<3;i++)
t[i]=new test();
for(int i=0;i<3;i++)
t[i].fun(); // now fine.
}
}
为什么在java中必须使用class的构造函数单独创建对象,而在C++中却不需要使用class的构造函数单独创建?
请帮助我。
简短的回答只是因为语法(几乎相同)并不意味着它的工作原理相同。实际上,由于 Student s[]
与您的 Java 代码等效的 C++ 代码是:
Student** s = new Student*[3];
然后您可以像这样初始化学生:
s[0] = 新学生("Jimmy");
这是一个需要掌握的重要概念,因为 Java 并不是唯一以这种方式不同于 C++ 的编程语言。
这是一个完整的示例,您可以尝试一下。使用 g++ 4.3.2
编译#include <iostream>
#include <string>
class Student {
public:
Student() : name_("<unknown>") {
std::cout << "Default constructor called" << std::endl;
}
Student(const char* name) : name_(name) {
std::cout << "constructor called with name '" << name << "'" << std::endl;
}
void setName(const std::string& name) { name_ = name; }
const std::string& getName() const { return name_; }
private:
std::string name_;
};
void demoArrayOfValues() {
std::cout << "demoArrayOfValues()" << std::endl;
// Here the default constructor will be called 3 times because
// creating you're creating an array of objects
Student* s = new Student[3];
for (int x = 0; x < 3; ++x) {
std::cout << "Student[" << x << "] (byValue): " << s[x].getName() << std::endl;
}
s[0].setName("Jimmy");
s[1].setName("Sally");
s[2].setName("Susie");
for (int x = 0; x < 3; ++x) {
std::cout << "Student[" << x << "] (after setting): " << s[x].getName() << std::endl;
}
std::cout << std::endl;
}
void demoArrayOfPointers() {
std::cout << "demoArrayOfPointers()" << std::endl;
// This is the C++ equivalent of the Java example that started the question
// Here you're creating an array of pointers and have to create the objects
// themselves
Student** s = new Student*[3];
for (int x = 0; x < 3; ++x) {
std::cout << "Student[" << x << "] (pointer): " << s[x] << std::endl;
}
s[0] = new Student("Jimmy");
s[1] = new Student("Sally");
s[2] = new Student("Susie");
for (int x = 0; x < 3; ++x) {
std::cout << "Student[" << x << "] (after creating): " << s[x]->getName() << std::endl;
}
std::cout << std::endl;
// Now we iterate over the elements in the array and delete each one.
for (int x = 0; x < 3; ++x) {
delete s[x];
}
// Now we delete the array itself
delete [] s;
}
int main(int argc, const char** argv) {
demoArrayOfValues();
demoArrayOfPointers();
return 0;
}