1

I have two classes

class A {

public:
    virtual void doStuff() = 0;
};

class B : public A {
    int x;

public:
    virtual void doStuff() override { x = x*2;} //just example function
};

And another class that modify and use data from the previous

class Foo {
    A a;

public:
    Foo::Foo(A &a_) : a(a_) {}

};

now I create the objects, and passes to the Foo class

B b;
// edit b attributes, 

Foo foo(b);

So at the argument list for the class constructor I know there is not the problem of object slicing, because is a reference, but what is the case at the moment of assign the variable a(a_)?

Since I don't know how much time the object b is going to live I need to make a secure copy. I have a lot of different derived classes from A, even derived from the derived.

Will there be a object slicing?,

Is there a solution to this, or I need to pass pointers (don't want this approach)?

quetzalfir
  • 528
  • 7
  • 22

3 Answers3

3

This causes slicing. C++ built in polymorphism only works with pointer/reference semantics.

In fact:

class Foo {
  A a;

that won't even compile, because A is not a concrete class.

To fix this, first make virtual ~A(){}; and then pass smart pointers to A around. Either unique or shared.


Failing that you can use your own bespoke polymorphism. The easiers way is to stuff a pImpl smart pointer as a private member of a class and implement copy/move semantics in the holding class. The pImpl can have a virtual interface, and the wrapping class just forwards the non-overridable part of the behaviour to it.

This technique can be extended with the small buffer optimization, or even bounded size instances, in order to avoid heap allocation.

All of this is harder than just using the built in C++ object model directly, but it can have payoff.

To see a famous example of this, examine std::function<Sig> which is a value type that behaves polymorphically.

Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524
1

There will be object slicing with what you currently have. You're calling the A copy-constructor in Foo's constructor, and there aren't virtual constructors. Having a member variable of type A only reserves enough space within an instance of Foo for an instance of A. There is only dynamic binding with pointers and references (which are pointers under the hood), not with member variables.

You would have to use pointers to get around this or you could rethink whether you really need a set-up like this.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
Gabriel
  • 829
  • 5
  • 12
0

Yes, there is slicing.

There has to be slicing, because a B does not fit inside a A, but it is an A that you are storing inside the class Foo. The B part is "sliced off" to fit; hence the name.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055