A Base Class pointer can point to a derived class object. Why is the vice-versa not true?
基类指针可以指向派生类对象。为什么没有铸造,反之亦然?从逻辑上讲,基类将没有足够的派生类信息,但派生类也应该具有基类信息。我这里缺少一些基础知识。
如果我告诉你我有一只狗,你可以放心地假设我有一只宠物。
如果我告诉你我有宠物,你不知道那动物是狗,它可能是猫,甚至可能是长颈鹿。如果不知道一些额外的信息,你就不能安全地认为我养了一条狗。
类似地,派生对象是一个基类对象(因为它是一个子类),所以它可以由一个基类指针指向。但是,基类对象不是派生类对象,因此不能将其分配给派生类指针。
(你现在听到的吱吱声是比喻的延伸)
假设你现在想给我的宠物买件礼物。
在第一种情况下,你知道它是一只狗,你可以给我买一条皮带,每个人都很高兴。
在第二种情况下,我没有告诉你我的宠物是什么,所以如果你无论如何都要给我买礼物,你需要知道我没有告诉你的信息(或者只是猜测),你给我买了一条皮带,如果结果证明我真的养了一条狗,每个人都很高兴。
然而,如果我真的有一只猫,那么我们现在知道你做了一个错误的假设(CAST),并且有一只不快乐的猫被拴在皮带上(运行时错误)。
我们有两个物体。
1 2 3 4 5 6 7 | class A { int a; }; class B : A { int b; }; |
分配
分配
因为基类不是派生类。
当你有一个指向类型的有效指针时,你会说指向的对象在某些位置上会有一些数据,这样我们就能找到它。如果您有一个指向派生对象的指针,那么您保证指向的对象包含派生对象的所有数据成员——但是当您指向一个基,那么它就不会受到影响,并且会发生不好的事情?.
但是,派生的保证在同一位置上具有所有基本数据成员。这就是为什么指向基的指针实际上可以指向派生的。
因为派生类包含基类中的所有内容。但基类并不包括派生类中的所有内容。
不建议将基类强制转换为派生类:如果尝试访问不属于基类的成员,会发生什么情况?
这是有效的,因为老虎是动物:
1 | Animal * pAnimal = new Tiger(); |
这是无效的,因为这个物体不是真的是一只毒镖蛙。
1 | PoisonDartFrog * pPoisonDartFrog = new GenericFrog(); |
简短的回答
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | class A{ public: method1(); }; class B: public A{ public: method2(); }; int main(){ // Case 1 A* ptr_base = new B(); // Here I can call all the methods in A by ptr_base even though it is assigned B ... // ... because B is derived from A and has all the information about methods of A // Case 2 B* ptr_derived = new A(); // this will cause error // Now here ptr_derived is assigned information of A ... // ... So with this information can I call (*ptr_derived).method2(); ?... // ... the answer is No because A does not have information of method2() ...; // ... thus this declaration loses its meaning and hence error. return 0; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | 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 |
因为C++是静态类型的语言,并且允许隐式基类派生的转换会破坏类型系统。bjarne stroustrup不希望出现任何"消息无法理解"的运行时错误。
通常,一个类型的指针不能指向其他类型的对象。但是,这个规则有一个重要的例外,它只涉及YO派生类。在这种情况下,类型base*的指针可以指向派生类型的对象,即基类指针可以指向派生类对象,反之亦然,因为基对象不是它的子类对象。
如果将一个地址从一个基类指针分配到一个派生类指针中,则可以潜在地将一个基类对象分配给一个派生类指针。如果没有派生类,则有访问派生类成员的风险。虽然派生类方法可以在基类上工作,但是只有当方法不访问派生类成员数据时,它们才会这样做。
这是一个巨大的风险。
所以我们强迫你投,所以你必须承认免责声明说(你可能犯了一个愚蠢的错误,请小心)。
因为基类指针可以指向基类或任何派生类型的实例。派生指针只能指向该派生类型或其任何子类。
1 2 3 4 5 6 | 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. |
至于原因:一般来说,基指针比派生指针更通用。因此,它对继承类型了解得更少。派生指针不能在不强制转换的情况下分配给基类型的指针,因为它无法判断基指针是派生类型还是其子类型之一。