c ++ newbie here
所以我正在查看类在c ++中是如何工作的,我编写了这段代码:
class A{
...
}
class B: public A{
...
}
int main(void){
A array[10];
}
c ++中的继承是否与Java中的继承相同?
我可以在数组中添加B类型的对象吗?如果是这样,我该怎么做?
只是做array[0] = new B();
不起作用
P.S。只是一个后续问题,有人可以向我展示一个具有简单构造函数的类对象数组的快速示例吗?出于某种原因,我遇到了问题。如果它有点复杂,我会发布另一个问题。提前致谢
答案 0 :(得分:3)
在Java中,类类型的变量始终是对象的引用。即。
A a = new A();
A a2 = a; // now a and a2 represent the same object
a.x = 12; // now print(a2.x) will also output 12
new A()
将在堆上创建实际对象(可以动态分配的内存区域),并返回它的内存地址。 a
和a2
将(内部)实际上只包含该地址。
与包含实际值的整数类型变量不同,所以:
int a = 1;
int a2 = a;
a = 3;
// now a2 will still be 1
在C ++中,对象被放在堆栈中,与整数类型相同(除非您使用引用或指针)。所以:
class A {
public:
int x;
};
A a;
A a2;
a.x = 1;
a2 = a; // actually calls a2.operator=(a) which is implicitly defined, and assigns all data members (here only int x) the values from the other A
a.x = 2;
std::cout << a2.x << std::end; // will output 1
对于数组仍然如此:如果声明数组A as[10]
,则在堆栈上分配一系列10个A对象。
如果你有
class A {
public:
int x;
};
class B : public A {
public:
int y;
};
A a;
a.x = 1;
B b;
b.x = 2;
b.y = 500;
// and then:
a = b; // now a.x == 2, but a holds no information about the y value
// with arrays it is the same:
A as[2];
as[0] = b; // now as[0].x == 2, --
执行a = b
仅将b
中超值类的值复制到a
。
A a;
a.x = 1;
A& a_ref = a;
现在a_ref
是对a
的引用
与Java不同,不能引用另一个对象。
相反,执行a_ref = a2
会产生与a = a2
a.x = 2
std::cout << a_ref.x << std::endl; // now outputs 2
与Java不同,a
只要存在a_ref
就必须存在,否则a_ref
无效,访问它会导致程序崩溃。在Java中,对象在堆上分配,并且仅在不存在指向它的引用时才释放(这称为垃圾回收)。
B b;
A& a_ref2 = b;
// now a_ref2 is a reference to b.
// (aka B has been downcasted)
// to access b.y from a_ref2, you could do:
int the_y = static_cast<B&>(a_ref2).y
建议不要使用此(静态上传),只有在您确定a_ref2
指向B
对象时才有效。否则它会填充段错误/崩溃。
如果A
是多态的(见下文),则可以使用dynamic_cast<B&>(a_ref2)
代替(仍然不推荐)。如果a_ref2
不是B
,它会检测错误并抛出异常。
class A {
public:
virtual int get_v() { return 1; }
int get() { return 1; }
int get_a() { return 3; }
};
class B : public A {
public:
int get_v() override { return 2; } // 'override' is not needed, and only works in C++11
int get() { return 2; }
};
B b;
A& a_ref = b;
b.get_v(); // returns 2
b.get(); // returns 2
b.get_a(); // returns 3, by inheritance
a_ref.get_v(); // returns 2, because get_v is a virtual function.
由于虚函数A和B是多态类。在编译时不知道这是否会调用A::get_v
或B::get_v
,因为a_ref
的类型为A&
。相反,调用函数在运行时决定,具体取决于a_ref
指向的内容。在Java中,所有函数都是这样的。
a_ref.get(); // returns 2.
由于get()
不是多态的,因此调用A
get()
函数,因为a_ref
的类型为A&
。
a_ref.get_a(); // returns 3, by inheritance
指针就像引用,但是更低级别。您可以使用与实际对象(a_ref.x
和b.x
)相同的方式访问引用。指针变量是地址。与引用不同,它们可以在初始赋值后指向另一个对象:
B b; // same classes A and B as before
A* a_ptr = &b; // a is now a pointer to b.
// The type A* means "pointer to B". &b means "address of b".
// Polymorphism works the same:
a_ref->get_v(); // returns 2
a_ref->get(); // returns 2.
a_ref->get_a(); // returns 3.
动态内存分配也会返回指针:
A* a_ptr = new B(); // a_ptr is now a pointer to a B allocated on the heap
...
delete a_ptr; // must be done to deallocate the B, otherwise there will be a memory leak.
因为a_ptr的类型为A*
(而不是B*
),所以多态类的析构函数应该是虚拟的:
class A {
public:
...
virtual ~A() { .... }
};
class B : public A {
public:
...
~B() override { .... }
};
否则只会调用A::~A
。
所以在你的情况下,你可以这样做:
A* array[10];
array[0] = new B();
array[0]->get_v();
delete array[0];
但是数组中尚未初始化的所有指针都是无效的。即array[1]->get_v()
或delete array[1]
会出错。
array
将是指向A
类型的对象或A
的子类的指针数组。
您还可以动态分配A这样的数组:
A* array = new[10] A; // array is now a pointer to an array
array[0].x = 1;
delete[] array; // Deallocates as many items as where allocated
但这和前面的A as[10]
一样,只是在堆栈上。这些是A
个对象,执行array[0] = b
只会从b.x
复制b
。
一个好的解决方案可能是使用STL中的std::unique_ptr
。它是指针的包装器,这样任何两个unique_ptr
都不能指向同一个项目。 (因为禁止复制unique_ptr
等):
#include <memory>
// needed for std::unique_ptr
std::unique_ptr<A> array[10];
array[0].reset( new B() ); // needed to assign a value to it
array[0]->get_v();
按预期工作。未分配值的array
元素默认初始化为零。访问它们会抛出异常而不是段错等。
不能为=
分配项目(因为语义不同)。相反,reset
指定指针。如果之前有另一个指针,那么首先是delete
&#39}。同样不需要(或可能)delete array[0]
,unique_ptr
会在变量array
超出范围时删除项目。
允许多个指针指向同一个对象的解决方案,这样只有当没有指针指向它时对象才会被解除分配,这个解决方案也在STL中:shared_ptr
。
对于堆栈中的项目数组,如
A array[10];
它将始终调用默认构造函数(不带参数)。没有办法将参数传递给它。
std::array
可以进行复制初始化(即构造函数采用单值:)
class A {
public:
int x;
A(int nx) : x(nx) {}
};
std::array<A, 3> ar = { 1, 2, 3 };
// or
std::array<A, 2> ar2 = { a, a2 }; // makes copies