3

I have a class hierarchy and I want to forbid doing this:

Foo *f = new Foo();
Bar *b = new Bar();

f = b;

where Foo is a superclass of Bar. Doing this would slice the Bar part of the object. I know you can solve this by making operator= private, but is it possible to only forbid the assignment operator from being used if they are of different types?

Like making operator= private but still allowing this:

Bar *b1 = new Bar();
Bar *b2 = new Bar();

b1 = b2;

Assume subclasses will be made to Bar as well.

Topsic
  • 109
  • 1
  • 9
  • Where is `operator=` declared? – Cameron Dec 20 '12 at 16:47
  • 6
    You aren't assigning `Foo` or `Bar` objects in this example. You are assigning **pointers** to `Foo` or `Bar`. Your example doesn't match your question. And no, you can't disallow pointer assignment. – Robᵩ Dec 20 '12 at 16:47
  • if you need both a `Foo` and `Bar` object is it possible to not use inheritance and use interfaces instead? – andre Dec 20 '12 at 16:48
  • Oh I see, so if I force the using of pointers I wont have this problem? – Topsic Dec 20 '12 at 16:51
  • I notice that you're asking about preventing slicing but as your left-hand side is already an object known to be of parent size, what's the *real* problem you're trying to solve? Is it always unwanted in your case to assign non-identical types? – Mark B Dec 20 '12 at 16:57
  • @Ceilingbat Preventing slicing for the sake of preventing slicing isn't usually needed in C++ although there are some underlying cases where it might be useful, hence my earlier question. – Mark B Dec 20 '12 at 17:35

3 Answers3

4

Since you are talking about slicing, I assume what you are actually trying to prevent is this:

Foo f;
Bar b;

f = b;

In this case, yes, you can prevent the assignment by making the appropriate operator= private.

You cannot prevent pointer assignments, but note that a pointer assignment would not result in slicing anyways.

zennehoy
  • 6,405
  • 28
  • 55
  • Yes that is what I want to prevent, I'm quite new to C++ so...But if I force the use of pointers I will not have this problem? – Topsic Dec 20 '12 at 16:53
  • I recommend not implementing the *Virtual Assignment Idiom*, because the parent may point to a different kind of child than the other object. I would keep with the rule that assignment requires two of the same leaf or child types. – Thomas Matthews Dec 20 '12 at 16:59
  • 1
    If you use pointers, you will not have a problem with slicing. Whether the use of pointers is best for your application is difficult to tell from the limited information in the question. Forcing the use of pointers by some strange code constructs is probably not a good way to go... – zennehoy Dec 20 '12 at 17:01
  • I will be having a newInstance() sort of method that will return a pointer to the object, so that will force the use of pointers. That's not bad I think? – Topsic Dec 20 '12 at 17:06
2

This is out of your reach: user-defined operators must take at least one parameter of a user-defined (not built-in) type. Since pointers are built-in types, you are out of luck here. f = b will be legal no matter what you do.

Gorpik
  • 10,940
  • 4
  • 36
  • 56
0

No slicing will occur in your example:

Foo *f = new Foo();
Bar *b = new Bar();

f = b;

You're assigning the pointer, not the value. The f pointer and the b pointer are the same size (the size of a pointer on the architecture you're running on), so they will always fit into each other with no slicing. The objects themselves aren't affected by this assignment and are not sliced.

But this would cause the 'new Foo()' to leak. After the assignment, both f and b will point to the 'new Bar()' and you'll have no pointer left to the 'new Foo()' which you would be able to delete it with.

Can I suggest you use std::unique_ptr instead of raw pointers. This will take care of deleting for you.

std::unique_ptr<Foo> newInstance()
{
    return new Foo();
}
Scott Langham
  • 58,735
  • 39
  • 131
  • 204