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++?

2
  • 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. Commented Aug 9, 2021 at 20:15
  • you can replicate behavior, but the code will be different. Commented Aug 9, 2021 at 20:36

2 Answers 2

2

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; 
Sign up to request clarification or add additional context in comments.

3 Comments

So if I have a function foo() which can return values of type Baseand of type DerivedI have to return Base*? Is this the proper way to do this in C++?
@Luke returning a std::unique_ptr<Base> 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).
@Luke yes, you would have to return a (smart) pointer in that case.
-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();

1 Comment

static_cast<Derived*>(bs)->fn(); would be preferred instead. Making fn() virtual so the cast is not needed at all would be even better.