Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is object slicing ever useful?

Object slicing happens when we assign or copy an object of derived class to an object of its base class, losing the derived part of it in the process.

It has been explained in more depth here: What is the slicing problem in C++?.

(Myself, I don't see it as a problem, rather a natural consequence of language's value semantics, but that's not the point of this question.)

What I wonder is: are there ever situations where you'd use it purposedly? A situtation where it is the "right tool for the job"?

like image 966
jrok Avatar asked May 07 '13 09:05

jrok


People also ask

Why do we use object slicing?

Object slicing is used to describe the situation when you assign an object of a derived class to an instance of a base class. This causes a loss of methods and member variables for the derived class object. This is termed as information being sliced away.

What is object slicing and how can we prevent it?

Object slicing can be prevented by making the base class function pure virtual thereby disallowing object creation. It is not possible to create the object of a class that contains a pure virtual method.

What is object slicing explain with example?

"Slicing" is where you assign an object of a derived class to an instance of a base class, thereby losing part of the information - some of it is "sliced" away. For example, class A { int foo; }; class B : public A { int bar; }; So an object of type B has two data members, foo and bar .

Does object slicing happen in Java?

In Java, objects are passed by reference, and all methods are virtual, so object slicing will not occur inadvertently. Even if you upcast an object, its real type is not forgotten, that's the definition of polymorphism.


2 Answers

Sure, it can be useful when wanting to drop the derived portion of class, perhaps to drop dependencies.

For example say we have an object system setup where each base belongs to a derived type, and each derived type has various dependencies, perhaps fulfilled through dependency injection. A clone of a base might want to be created, though a completely new set of dependencies for the actual derived type of that base may want to be assigned.

This can be likened to an game engine where there are many types of colliders. Each collider derives from a base interface-like object in various ways. We want to clone a collider to retrieve it's position and scale (from base), but want to place an entirely different derived implementation on-top of this base. "Object slicing" could be a simple way to achieve this.

In reality a component, or aggregate object organization would make a lot more sense than object slicing specifically, but it's mostly the same idea.

like image 61
RandyGaul Avatar answered Oct 16 '22 16:10

RandyGaul


Some STL implementations actually use object slicing to implement algorithms: E.g., using iterator_tags you can easily make std::advance use the most efficient algorithm:

namespace std {

template <class I>
void advance_impl(I& it, int n, input_iterator_tag) {
    for (; n > 0; --n)
        ++it;
}

// Forward Iterators use the same implementation as Input Iterators...

// TODO:
// Add bidirectional_iterator_tag implementation...

template <class I>
void advance_impl(I& it, int n, random_access_iterator_tag) {
    it += n;
}

template <class I>
void advance(I& it, int n) {
    advance_impl(it, n, typename iterator_traits<I>::iterator_category());
}

} // std

Using your own little class hierarchy you can disambiguate otherwise ambiguous function overloads. E.g. to convert an object to a std::string you might want to use the objects member function to_string() if it exists or otherwise use operator<<.

struct R2 {};       // rank 2
struct R1 : R2 {};  // rank 1

// C++11.
// Use some type traits and enable_if in C++03.
template <class T>
auto ToString(R1, T const& t) -> decltype(t.to_string()) {
    return t.to_string();
}

template <class T>
std::string ToString(R2, T const& t) {
    std::ostringstream s;
    s << t;
    return s.str();
}

template <class T>
std::string ToString(T const& t) {
    return ToString(R1(), t);
}
like image 1
user3250917 Avatar answered Oct 16 '22 14:10

user3250917