A Base Class pointer can point to a derived class object. Why is the vice-versa not true?

C++

C++ Problem Overview


A Base Class pointer can point to a derived class object. Why is the vice-versa not true without casting? Logically a base class would not have enough information of the derived class but a derived class should have the information of the base class as well. I am missing some basics here.

C++ Solutions


Solution 1 - C++

If I tell you I have a dog, you can safely assume that I have a pet.

If I tell you I have a pet, you don't know if that animal is a dog, it could be a cat or maybe even a giraffe. Without knowing some extra information you can't safely assume I have a dog.

similarly a derived object is a base class object (as it's a sub class), so it can be pointed to by a base class pointer. However, a base class object is not a derived class object so it can't be assigned to a derived class pointer.

(The creaking you will now hear is the analogy stretching)

Suppose you now want to buy me a gift for my pet.

In the first scenario you know it is a dog, you can buy me a leash, everyone is happy.

In the second scenario I haven't told you what my pet is so if you are going to buy me a gift anyway you need to know information I haven't told you (or just guess), you buy me a leash, if it turns out I really did have a dog everyone is happy.

However if I actually had a cat then we now know you made a bad assumption (cast) and have an unhappy cat on a leash (runtime error).

ClassCastException Cat

Solution 2 - C++

We have two objects.

class A {
   int a;
};

class B : A {
   int b;
};

Allocate an instance of B. We can interface with that as either an A* or a B*.

Allocate an instance of A. If we were to cast it to a B*, should there be space allocated for the member b?

Solution 3 - C++

Uh, because the base class is not a derived class.

When you have a valid pointer to a type, then you are saying that the object pointed to will have certain data in certain locations so that we can find it. If you have a pointer to a derived object, then you are guaranteeing that the pointed-to object contains all of Derived's data members- but when you point to a Base, then it infact doesn't have that and Bad Things Happen™.

However, Derived is guaranteed to have all of the Base data members in the same locations. That's why a pointer to Base can actually point to Derived.

Solution 4 - C++

Because a derived class includes everything that is in the base class. But a base class does not include everything that is in the derived class.

Type casting a base class to a derived class is not recommended: What happens if you try to access members that are not part of the base class?

Solution 5 - C++

This is valid, because a tiger is an animal:

    Animal * pAnimal = new Tiger();

This is not valid, because it is not true that the object is a poison dart frog.

    PoisonDartFrog * pPoisonDartFrog = new GenericFrog();

Solution 6 - C++

Because C++ is a statically typed language, and allowing implicit Base-to-Derived conversions would break the type system. Bjarne Stroustrup did not want any "message not understood" runtime errors.

Solution 7 - C++

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

Solution 8 - C++

The short answer

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;
}

Solution 9 - C++

This is because, "the type of a pointer is the type of object the pointer points to". So,

  1. If we have base type pointer (*B):

then we expect a base type object (and would like to access its functionalities) at the address pointed by B, and if we get a derived type object at that address then also we are able to access the required functionalities. This is because derived type is-a base type.

  1. If we have derived type pointer (*D):

then we expect a derived type object at the address pointed by D and if we get base type object there then we will not be able to access derived class info from the base type object since base type is-not-a derived type.

Solution 10 - C++

Actions speak more than words. Child too can have Parent Class object. if you understand pointers well, limitations are off to you In below code have printed both values by child class pointer ( which was having Parent class object). Also proved that by printing their address. Any suggestions are welcome!

#include<iostream>
using namespace std;
class Baap{
    public:
        int a;
        void hoo(){ cout<<"hoo\n"; cout<<a;}
};

class Beta:public Baap{
    public:
        int a;
        int b;
        void hee(){ cout<<"hee\n"; }
};
    
int main(){
    Baap baap;
    baap.a=1;
    Beta *beta=(Beta*)&baap;
    baap.a=3;
    beta->hee();
    beta->hoo();
    cout<<"\n beta = "<<beta<<"\n&baap = "<<&baap;
    return 0;
}
//output
 hee                                                                                                                           
 hoo                                                                                                                           
 3                                                                                                                             
  beta = 0x7ffd11dd3834                                                                                                        
 &baap = 0x7ffd11dd3834 

Solution 11 - C++

Because a base class pointer can point to an instance of the base class or any derived type. A derived pointer can only point to that derived type or any subclass of it.

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.

As far as the why goes: In general the base pointer is more general than the derived pointer. As such it knows less about the inherited type. A derived pointer cannot be assigned a pointer to a base type without casting simply because it cannot tell if the base pointer is of the Derived type or one of its children.

Solution 12 - C++

If assign an address from a base class pointer into a derived class pointer, you can potentially assign a base class object to a derived class pointer. You run the risk of accessing derived class members when you don't have a derived class. Whereas derived class methods would work on a base class, they would only do so if the method didn't access derived class member data.

That's a huge risk.

So we force you to cast so that you have to acknowledge the disclaimer that says (you may make a stupid mistake, please be careful).

Solution 13 - C++

In general , a pointer of one type cannot point to an object of a different type. However, there is an important exception to this rule that relates only to derived classes.

In this situation a pointer of type BASE* may point to an object of type Derived, i.e a base class pointer can point to a derived class object but vice versa is not true as the base object is not it's sub class object.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionZuzuView Question on Stackoverflow
Solution 1 - C++jk.View Answer on Stackoverflow
Solution 2 - C++Bill LynchView Answer on Stackoverflow
Solution 3 - C++PuppyView Answer on Stackoverflow
Solution 4 - C++Jonathan WoodView Answer on Stackoverflow
Solution 5 - C++Andy ThomasView Answer on Stackoverflow
Solution 6 - C++fredoverflowView Answer on Stackoverflow
Solution 7 - C++YoungJohnView Answer on Stackoverflow
Solution 8 - C++Peri JaviaView Answer on Stackoverflow
Solution 9 - C++VickyView Answer on Stackoverflow
Solution 10 - C++Vinod SinghView Answer on Stackoverflow
Solution 11 - C++WashuView Answer on Stackoverflow
Solution 12 - C++Lee LouviereView Answer on Stackoverflow
Solution 13 - C++Abhishek Raj PermaniView Answer on Stackoverflow