我有一个关于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;
}
答案 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对象,而不是相反。