1

I will describe my problem using a dummy example. Say we have a program of this architecture:

Parent class: Quadrilateral

Child classes: Rectangle, Rhombus, ...

First, a vector<Rectangle> and vector<Rhombus> are generated and make use of their child class properties. Later on, I would like to combine all quadrilaterals, i.e. combine both vectors into a single vector<quadrilateral>, since I no longer need the child class properties. Combining both vectors into one has the advantage that I can pass a reference to vector<quadrilateral> to other parts of my program where it is combined with data from other classes.

So my question is as follows: Is it possible to make a Quadrilateral out of a Rectangle by keeping only the parent variables from the Rectangle? Or is this a really bad idea and is there a much more elegant way to implement this?

EDIT:

after learning from the answers that this is referred to as slicing, I have read about it in What is object slicing?. I have decided to go with Mohamad's suggestion of using vectors of pointers instead, because I think it is an elegant solution that will likely give me the best performance.

Community
  • 1
  • 1
Bart
  • 190
  • 2
  • 8
  • maybe all what you need is to create a copy constructor for Parent class. correct me if i'm wrong – feech Oct 01 '15 at 21:44

2 Answers2

1

Yes, you can do this. You can create parent objects from child objects, as in following example:

struct Base { int base; };

struct Derived : Base { int derived; };

Derived der;
Base base = der;

The process is called slicing, and it works here because Base class will have default copy constructor, taking a const reference to Base. Since derived can be automatically converted to const reference to it's base, everything works like the charm. I am not sure about overall design, though. Usually slicing is to be avoided.

Following some questions in the comments, I believe, some clarification is in order.

Contrary to it appearance, Base base = der; does not call assignment operator. Instead, it calls copy constructor - this is the semantic of variable declaration. It is equivalent of Base base(der). Here is more intruiging example:

struct A {
   A(int ) { };
   A() = default;
   // A(const A& ) = delete;
};

A a = 5; // Are your eyes fooling you?

Do not believe your eyes! There is never an operator= called - there is no even operator= in A defined. Instead, semantically A(int) constructor is called to create a temporary A, followed by copy constructor to create the a object. However, compilers usually optimize the call to copy-constructor away, and there is no redundant temporary copy created. In order to make sure this the case, uncomment copy-constructor marked delete, and the program will refuse to be compiled.

SergeyA
  • 61,605
  • 5
  • 78
  • 137
  • by looking at your code you meant default ' copy assignment operator=' not 'copy constructor' correct me if I was wrong – RaGa__M Oct 01 '15 at 16:52
  • @RichardGeorge, yes, you are very wrong. There is no assignment operator call in my code. – SergeyA Oct 01 '15 at 16:54
  • @RichardGeorge: This would use assignment operator: `Base base; base = der;`, `Base base = der;` does not. It's equivalent to `Base base( der );` – jpo38 Oct 01 '15 at 16:55
  • So there is no such thing like Default copy assignment operator that do necessary task when you assign one compatable object to an another as told in websites and books – RaGa__M Oct 01 '15 at 17:00
  • @RichardGeorge, of course there is! It is just not called here. I have updated my post to add some details on this. – SergeyA Oct 01 '15 at 17:04
  • A bit thing I am sure as you said for A a=5; the copy assignment won't call as 5 is an attribute not derived one is that the same for Base base=der; – RaGa__M Oct 01 '15 at 17:10
  • @RichardGeorge, you are confused. Your confusion starts with the fact that you are mentioning non-existing 'copy assignments'. There are copy constructors and assignment operators, two different beasts. What do you mean by 'attribute not derived one' is completely beyond my comprehension. – SergeyA Oct 01 '15 at 17:13
  • Well ,I meant int 5 may be an attribute or member of struct A but it is not a child of A,so the way = act will differ any way thank you for the replies I will watch out what confused me . – RaGa__M Oct 01 '15 at 17:26
1

Yes you can definitely do this by 'slicing' the derived portion of the object.

class Base {};
class Derived : public Base {};

Derived d;
Base b = d; // derived portion is sliced here

However in practise, I have never seen anyone who deliberately chose to slice their objects. We are usually warned against this as a 'gotacha' of C++.

Why not use a vector of pointers instead:

vector<Rectangle*>;
vector<Rhombus*>;
vector<quadrilateral*>;

That way no slicing occurs and you might gain from a performance boost if those classes are large since any copying the vectors might do would be on pointers and not entire objects.

Mohamad Elghawi
  • 2,071
  • 10
  • 14