如何将Base对象分配给Derived对象

时间:2010-01-30 00:10:33

标签: c++

我有一个关于C ++的问题,如何将Base对象分配给Derived对象?或者如何将指向Base对象的指针指向指向Derived对象的指针?

在下面的代码中,两行是错误的。如何纠正?

#include <iostream>
using namespace std;
class A{
public:
   int a;
};

class B:public A{
public:
   int b;
};

int main(){
    A a;
    B b;
    b = a; //what happend?
    cout << b.b << endl;   

    B* b2;
    b2 = &a;        // what happened?
    cout << b->b << endl;
}

5 个答案:

答案 0 :(得分:4)

将基础对象分配给派生(或指向派生指针的基指针)是没有意义的,因此C ++将尽力阻止您这样做。例外情况是当基指针真正指向派生时,在这种情况下你可以使用动态强制转换:

base * p = new derived;
derived * d = dynamic_cast <derived *>( p );

在这种情况下,如果p实际指向基数,则指针d将包含NULL。

答案 1 :(得分:2)

编译器不会允许这种事情。即使你设法通过一些铸造黑客来做到这一点,这样做是没有意义的。将派生对象分配给基础的指针是有意义的,因为基础可以执行的所有操作都可以执行。但是,如果允许相反的情况,如果您尝试访问在基础对象上派生的成员,该怎么办?您将尝试访问充满垃圾或无关数据的内存区域。

答案 2 :(得分:2)

当一个对象在堆栈上时,您只能真正地将相同类型的对象彼此分配。它们可以通过重载的强制转换运算符或重载的赋值运算符进行转换,但是您在此时指定了转换。编译器本身无法进行此类转换。

A a;
B b;
b = a;

在这种情况下,你试图将A分配给B,但A不是B,所以它不起作用。

A a;
B b;
a = b;

经过一段时间后,这确实有效,但它可能不会是你所期望的。你只是切了你的B. B是A,所以可以进行赋值,但因为它在堆栈上,所以它只是将b的一部分分配给a的一部分。所以,你得到的是A.尽管你是从B分配的,但它不是B。

如果你真的想要将一种类型的对象分配给另一种类型,那么它们需要成为指针。

A* pa = NULL;
B* pb = new B;
pa = pb;

这很有效。 pa现在指向pb,所以它仍然是B.如果你有A和B的虚拟功能覆盖它们,那么当你在pa上调用它们时,它们将调用B版本(非虚拟的仍将调用A版本) )。

A* pa = new A;
B* pb = pa;

这不起作用。 pa不指向B,因此你不能将它指定给必须指向B的pb。仅仅因为B是A并不意味着A是B。

A a;
B* pb = &a;

这与前一个原因相同。碰巧这次A在堆栈上而不是堆。

A* pa;
B b;
pa = &b;

这确实有效。 b是B,它是A,所以A可以指向它。虚函数将调用B版本,非虚函数将调用A版本。

所以,基本上,A *可以指向B,因为B是A. B *不能指向A,因为它不是B。

答案 3 :(得分:1)

b = a; //what happend?

这是非法的 - A不是B,所以你不能这样做。

b2 = &a;        // what happened?

同样在这里。

在这两种情况下,编译器都不知道要分配给int b的内容,因此他会阻止您这样做。反过来(将Derived分配给Base)有效,因为Base是Derived的子集

现在,如果您告诉我们,您想要实现的目标,我们可能会帮助您。

如果是分配已知为派生类型的A的情况,您可以进行投射:

A* a = new B();
B* b = dynamic_cast<B>(a);

请记住,如果a不是B,那么dynamic_cast将返回NULL。请注意,此方法仅适用于指针,原因为

答案 4 :(得分:0)

派生对象是一种Base对象,而不是相反。