0

I am confused about the term upcasting in c++ (for example here). Is it really a casting? For example when I cast a an int to a double, I expect the casted type to behave exactly as a double. However, if I upcast a derived class to a base class it seems the casted object doesn't behave exactly as an object of the base class as the following code shows :

class Base {
public:
    virtual void print() { cout << "base" << endl; }
};

class Derived :public Base {
public:
    void print() { cout << "derived" << endl; }

};

void main()
{
    // Upcasting
    Derived d;
    Base* pBase = &d;
    
    // test
    Base b;
    Base* pBase2 = &b;

    if (dynamic_cast<Derived*>(pBase));
    {
        cout << "1st upcasting ok" << endl;
    }

    if (dynamic_cast<Derived*>(pBase2))
    {
        cout << "2nd ucasting ok" << endl;
    }
}

output :

1st upcasting ok
roi_saumon
  • 489
  • 4
  • 13
  • 3
    Any explicit conversion is a cast. But those are both *down*casts, from the base type to the derived type. And you're casting pointers, not the objects they point to. – molbdnilo Mar 29 '23 at 14:19
  • 5
    `dynamic_cast(pBase2)` fails because `pBase2` doesn't point to a `Derived` object. That's kind of the point of `dynamic_cast`. – Some programmer dude Mar 29 '23 at 14:20
  • 2
    I would recommend that you get [a good book](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list/388282). (That's a pretty terrible page you've found.) – molbdnilo Mar 29 '23 at 14:26
  • 1
    I'm not sure how you can think that `dynamic_cast(pBase)` is casting a derived class to a base class. It's clearly going the other way. – john Mar 29 '23 at 14:28
  • 1
    "if I upcast a derived class to a base class" -- that's not what the shown code does. It attempts to cast a pointer to a base class to a pointer to a derived class, in exactly the opposite direction. Another vote for [a good C++ textbook](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list). – Sam Varshavchik Mar 29 '23 at 14:29
  • Related: https://stackoverflow.com/a/35102183/4641116 – Eljay Mar 29 '23 at 14:30
  • 1
    `if (dynamic_cast(pBase));` <--- !! note the `;` You will always print `"1st upcasting ok"` no matther if the casting actually suceeded – 463035818_is_not_an_ai Mar 29 '23 at 14:33
  • `Derived d; Base* pBase = &d;` is what I was referring as upcasting (as suggested in the comment) because it is the terminology they used in the link. I know that `dynamic_cast(pBase)` is downcasting. – roi_saumon Mar 29 '23 at 14:35
  • 1
    if you refer to `Base* pBase = &d;` as upcasting then why is the `"1st upcasting ok"` output on the `dynamic_cast` ? ANd what do you mean with " it seems the casted object doesn't behave exactly as an object of the base class as the following code shows :" ? – 463035818_is_not_an_ai Mar 29 '23 at 15:03

2 Answers2

2

You raise a good point. In C++, upcasting is technically not a casting operation in the same sense as, say, converting an int to a double, because no actual conversion of the object takes place.

When a derived class object is upcast to a base class pointer, the derived class object is treated as if it were an object of the base class. The actual object remains a derived class object, but the pointer to that object can be treated as a base class pointer, allowing access only to the members of the base class.

In your example, the upcasted object can only access the Base class members, even though it is actually an object of the Derived class. The print function called on the upcasted object will call the print function of the Base class, because that is the version of the function defined in the base class. However, if the print function was declared as virtual in the Base class and overridden in the Derived class, then the print function of the Derived class would be called if the object was actually a Derived object, even if it was upcasted to a Base pointer.

So while upcasting technically isn't a casting operation in the same sense as type conversion, it is a common way to treat derived class objects as base class objects in C++.

Cole nelson
  • 84
  • 1
  • 5
  • Thank you. "the pointer to that object can be treated as a base class pointer", is this what is referred to as slicing? Is this usually done under the hood by manipulating the virtual tables or virtual pointers? – roi_saumon Mar 29 '23 at 14:46
  • 1
    *is this what is referred to as slicing?* **No**, slicing would be like `Base b = d;`. *Is this usually done under the hood by manipulating the virtual tables or virtual pointers?* **No,** the RTTI data structures are const; they may be traversed in order to resolve the `dynamic_cast` but they won't be modified or manipulated. – Eljay Mar 29 '23 at 14:49
  • Um, in order to make categorical statements about what "upcasting" does or doesn't do in C++ you have to rigorously define it, not just wave your hands around with vague examples. I would certainly expect that "upcasting" an object of a derived type to an object of a base type would make a new copy of the object, absent some truly perverse definition of "upcast". And, in general, you cannot cast "a derived class object ... to a base class pointer". There's a grain of truth in this answer, but it's hidden by vagueness and sloppy wording. – Pete Becker Mar 29 '23 at 17:03
  • @PeteBecker sorry, I thought it was being clear and direct. – Cole nelson Mar 29 '23 at 20:31
  • I had to think a while now I am understanding upcasting like this : If we define a base class `A` and a derived class `B`, I would imagine that the way the computer represents `B` is by appending the information specific to the derived class to the code of the base class. And so when doing `A* a = new B`, `a` points to an object `B` but since the pointer has `A` type we can access only the part specific to `A` from it. Then if we do `B* casted = static_cast(a)` or `B* casted = dynamic_cast(a)`, casted still points to a but since the pointer type is `B*` it can access the rest of `B`. – roi_saumon Mar 30 '23 at 06:59
  • I actually tried to do `double* x = new int` to see if this also worked for non class types but it doesn't which also makes sense since they don't have a portion in common so how to restrict in some sense what the pointer could access – roi_saumon Mar 30 '23 at 07:01
  • I probably got it all wrong because the way I see it upcasting would be a terrible name and I would call it polymorphic referencing or something like that... – roi_saumon Mar 30 '23 at 07:02
1

Upcasting isn't strictly a C++ term. dynamic_cast on a pointer doesn't create new object.

In first case you have object of Derived class-type, to wit Base is one of base classes. If you assign its address to a pointer to Base, you still have same object. For pBase the derived class is dynamic type, while its static type is Base. You need dynamic_cast to properly obtain pointer to dynamic type.

In second case static and dynamic type is same. You don't have an object of Derived. dynamic_cast returns null pointer.

Swift - Friday Pie
  • 12,777
  • 2
  • 19
  • 42