gpt4 book ai didi

c++ - C++继承和数组

转载 作者:搜寻专家 更新时间:2023-10-31 01:02:49 24 4
gpt4 key购买 nike

C++新手在这里

因此,我检查了类在c++中的工作方式,并编写了以下代码:

class A{
...
}
class B: public A{
...
}
int main(void){
A array[10];
}

c++中的继承是否与Java中的继承相同?
我可以在数组中添加类型B的对象吗?
只是做 array[0] = new B();不起作用

附言只是一个后续问题,有人可以向我展示一个具有简单构造函数的类的对象数组的快速示例吗?由于某种原因,我对此有疑问。如果有点复杂,我将发布另一个问题。提前致谢

最佳答案

在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()将在堆(可以动态分配的内存区域)上创建实际对象,并返回其内存地址。 aa2实际上(内部)仅包含该地址。

与包含实际值的整数类型变量不同,因此:
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只会将其父类(super class)中 b中的值复制到 a中。

引用文献
A a;
a.x = 1;
A& a_ref = a;

现在 a_ref是对 a的引用
与Java不同,该引用不能指向另一个对象。
相反,执行 a_ref = a2a = 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 1.

由于 get()不是多态的,因此它会调用 Aget()函数,因为 a_ref的类型为 A&
a_ref.get_a(); // returns 3, by inheritance

指针

指针就像引用,但较低级别。您可以使用与实际对象( a_ref.xb.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_ptr->get_v(); // returns 2
a_ptr->get(); // returns 1.
a_ptr->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

unique_ptr

一个好的解决方案可能是使用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。另外,不需要(或可能)没有 delete array[0],当变量 unique_ptr超出范围时, array删除项目。

STL中还提供了一种解决方案,该解决方案允许多个指向同一对象的指针,以便仅在不再有指针指向该对象时才释放该对象。

数组构造函数

对于堆栈上的一组项目,例如
A array[10];

它将始终调用默认构造函数(不带参数)。没有办法将参数传递给它。
shared_ptr可以复制初始化(即,构造函数采用单个值:)
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

关于c++ - C++继承和数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26455818/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com