基类指针可以指向派生类对象。 为什么反之亦然?

基类指针可以指向派生类对象。 反之亦然,为什么不铸就不成? 从逻辑上来说,基类没有足够的派生类的信息,但派生类也应该具有基类的信息。 我在这里错过了一些基础知识。

如果我告诉你我有一只狗,你可以放心地假设我有一只宠物。

如果我告诉你我有一只宠物,你不知道那只动物是一只狗,它可能是一只猫,甚至可能是一只长颈鹿。 不知道一些额外的信息,你不能安全地认为我有一只狗。

类似的派生对象是一个基类对象(因为它是一个子类),所以它可以通过基类指针指向。 但是,基类对象不是派生类对象,因此无法将其分配给派生类指针。

(你现在将听到的吱吱声是类比拉伸)

假设你现在想为我的宠物买一件礼物。

在第一种情况下,你知道这是一条狗,你可以给我买一条皮带,每个人都很高兴。

在第二种情况下,我没有告诉你我的宠物是什么,所以如果你要给我买一件礼物,你需要知道我还没有告诉你的信息(或者只是猜测),如果你给我买皮带事实上,我真的有一只狗,每个人都很高兴。

但是,如果我真的有一只猫,那么我们现在知道你做了一个错误的假设(铸造),并有一个不幸的猫(运行时错误)。

ClassCastException Cat

我们有两个对象。

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

分配一个B的实例。 我们可以将它作为A*B*进行交互。

分配A一个实例。 如果我们把它投给B* ,是否应该为会员b分配空间?

呃,因为基类不是派生类。

当你有一个有效的指针指向一个types,那么你就是说,指向的对象将在某些位置有一定的数据,以便我们可以find它。 如果你有一个指向派生对象的指针,那么你要保证指向的对象包含Derived的所有数据成员,但是当你指向一个Base时,它实际上并没有那个和Bad Things Happen™。

但是,派生保证所有的基础数据成员在相同的位置。 这就是为什么一个指向Base的指针实际上可以指向Derived。

这是有效的,因为老虎是一种动物:

  Animal * pAnimal = new Tiger(); 

这是无效的,因为这个物体不是真正的毒镖蛙。

  PoisonDartFrog * pPoisonDartFrog = new GenericFrog(); 

因为派生类包含基类中的所有内容。 但是基类不包含派生类中的所有内容。

不build议将基类转换为派生类:如果尝试访问不属于基类的成员,会发生什么情况?

因为C ++是一种静态types的语言,并且允许隐式的基于派生的转换会破坏types系统。 Bjarne Stroustrup不希望有任何“消息未理解”运行时错误。

 class Base { public: int a; } class Derived : public Base { public: float b; } Base * pBase = new Base(); pBase->a = 7; // setting the value of a in the base // make a pDerived that points to the SAME DATA as pBase Derived * pDerived = pBase; pDerived->a = 5; // this would be okay, base has a public member 'a' pDerived->b = 0.2f; // error pBase has no data member b and pDerived // points to the SAME DATA as pBase 

因为基类指针可以指向基类的实例或任何派生types。 派生指针只能指向派生types或其任何子类。

 struct Base {}; struct Derived : Base {}; struct Derived2 : Base {}; Base* p = new Derived(); //Fine, Derived inherits from Base Derived* d = new Base(); //Not fine, Base is not an instance of nor derived from Derived. Derived* d2 = new Derived2(); // Also not fine, Derived2 derives from Base, but is not related to Derived. 

至于为什么会这样:通常基指针比派生指针更一般。 因此,它对inheritancetypes知之甚less。 一个派生指针不能被分配一个指向基types的指针而不需要转换,因为它不能告诉基指针是派生types还是它的一个子types。

如果将基类指针的地址分配给派生类指针,则可以将基类对象分配给派生类指针。 如果没有派生类,则存在访问派生类成员的风险。 虽然派生类方法可以在基类上工作,但只有在方法不能访问派生类成员数据时才会这样做。

这是一个巨大的风险。

所以我们强迫你施放,这样你必须承认这个声明(你可能犯了一个愚蠢的错误,请小心)。