C ++继承和数组

时间:2014-10-19 21:52:29

标签: c++ arrays inheritance

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。只是一个后续问题,有人可以向我展示一个具有简单构造函数的类对象数组的快速示例吗?出于某种原因,我遇到了问题。如果它有点复杂,我会发布另一个问题。提前致谢

1 个答案:

答案 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()将在堆上创建实际对象(可以动态分配的内存区域),并返回它的内存地址。 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仅将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_vB::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.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_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

的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&#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