C++继承和数组
C++ inheritance and arrays
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()
将在堆(可以动态分配的内存区域(上创建实际对象,并返回它的内存地址。 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_ref
存在,a
就必须存在,否则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()
不是多态的,所以它调用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_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
复制b.x
。
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]
,当变量array
超出范围时,unique_ptr
会删除项目。
多个指针指向同一对象的解决方案,以便仅在没有指针指向对象时才解除分配对象,也在 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
- 继承:构造函数,初始化C++11中基类的类C数组成员
- 如何从 c++ 中类中内置的数组继承
- 从 std::数组私下继承时无法从 std::initializer_list 构造
- 删除C++中的继承类指针数组
- 继承向量/数组/列表并更改其大小
- 复制构造函数继承动态分配的数组
- 继承类的数组
- C++数组继承中的对象
- 继承构造函数不允许类似数组的初始化
- 在C++中扩展继承的数组
- 如何在C++中构建一个对象数组,这些对象都继承自一个主类
- C++类扩展(继承类中数组的不同大小)
- 指向从 1 个基类继承的不同类对象的指针数组
- 动态数组和类继承
- 继承和指针数组
- 有没有办法在继承类的基类中指定数组的大小
- 如何使数组包含从基类继承的类
- 不更新数组的继承机器人竞赛
- 有没有办法放入一个未定义大小的数组并作为静态数组继承
- 在函数中传递继承的类数组会导致内存泄漏