1

Let's imagine we have two classes.

class Base {};

class Derived : public Base {};

In another part of my code I want to have a variable of type Base which can also hold an object of type Derived.

Base b1, b2;
b1 = Base();
b2 = Derived();

In languages like Java or C# this is possible. In c ++, however, I get a slicing error.

Is there a way to replicate the behavior of for example Java in C++?

Luke
  • 365
  • 3
  • 10
  • 1
    Are you familiar with value types vs reference types in those other languages? Are you familiar with the concept that all classes in C++ are essentially value types by default? Are you familiar with pointers and references? If no the any of these questions, then there's the research/learning you need to do. – TheUndeadFish Aug 09 '21 at 20:15
  • you can replicate behavior, but the code will be different. – 463035818_is_not_an_ai Aug 09 '21 at 20:36

2 Answers2

3

In languages like Java and C#, object variables are reference types. The actual objects are stored somewhere in dynamic memory, and the variables just refer to them, like pointers.

But in C++, objects can be created in automatic memory, static memory, dynamic memory, etc. So when you have an object variable, that is the actual object, not a reference to the object.

There is no way to make C++ work the way you want for value types, only for reference types. So you MUST use a pointer/reference instead, otherwise slicing will occur, as you have already discovered. Polymorphism requires the use of pointers/references in order to handle virtual dispatch correctly, etc.

Base b;
Derived d;
Base &b1 = b;
Base &b2 = d;
Base *b1 = new Base;
Base *b2 = new Derived;
...
delete b1;
delete b2;
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • So if I have a function ```foo()``` which can return values of type ```Base```and of type ```Derived```I have to return ```Base*```? Is this the proper way to do this in C++? – Luke Aug 09 '21 at 20:30
  • @Luke returning a `std::unique_ptr` is the proper way to do it for a factory function (most of the time, it depends on where the responsibility for the destruction of the object lies). –  Aug 09 '21 at 20:33
  • @Luke yes, you would have to return a (smart) pointer in that case. – Remy Lebeau Aug 09 '21 at 20:35
-1

You can use pointers to accomplish that, ie this will work:

Base* bs=new Derived();

If you want to call a function that is defined in Derived, do the following:

((Derived*)bs)->fn();

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • 1
    `static_cast(bs)->fn();` would be preferred instead. Making `fn()` virtual so the cast is not needed at all would be even better. – Remy Lebeau Aug 09 '21 at 20:22