Slicing exists in various contexts of computing. I am talking about the Slice of an object. This usually happens in object-oriented languages. There the example was in vector, but not confused with the slicing of data collections which is something deliberate that the programmer has done. I’m talking about something that happens inadvertently in objects.
This interpretation above is correct?
That’s the idea, but not exactly like this, at least within what I know. It may even be that this may occur in some situation, but I’ve never seen something like the one shown (it may be my ignorance).
The slicing usually happens between types with inheritance relationship.
The problem of slicing seems to happen also in C for the same reasons; in which languages* is it most apparent? Has virtually shielded languages against this effect?
The phenomenon occurs inadvertently in weak typing languages (not to be confused with dynamic typing). Of course, in strong typing languages it is possible to reproduce the phenomenon if it explicitly allows you to change the type of an object without a conversion. This is rare in modern languages, even if Compile when doing this should give an error and it is not enough to present the slicing. By modern languages understand as managed languages. In a way only these languages can be considered completely strong in typing, but this is another subject.
C is a weak typing language and could occur, but it has no inheritance relation. Similar and even more serious problems would occur if the code really wanted to, but not exactly the slicing. The example shown in the question does something more serious, but for it to occur it takes some effort ;) The code has to ask for it to occur.
In C, and to some extent in C++, depending on the encoding style, it can corrupt memory, which is worse than the slicing, that wouldn’t even occur.
The slicing may occur within a homogeneous data vector? Or it is restricted to heterogeneous data?
Really homogeneous can not. Except for a deficiency of language implementation, but I dismiss this.
How does the slicing.
The slicing occurs when you wait for an object and come another with extended structure.
By structure understand the state. The slicing is not about behaviors, so if a derivative type adds nothing to the base object, you are free of the slicing. Some will say that in this case there was even a de facto inheritance.
Let’s see:
class Base
x : int
class Derivada : Base
y : int
b := Base()
d := Derivada() { x = 1, y = 2 }
b = d //funciona porque d é do tipo de b, nem toda linguagem deixa implicitamente
print b.x //sem problemas, dá 1
//print b.y //daria erro porque em b não tem y, então não temos problema aqui
d = b
print d.x //beleza, dá 1
print d.y //agora pode, d tem um y, mas imprime 2?
I put in the Github for future reference.
It turns out that b
does not have the element y
, he loses himself, when he turns and puts b
in the derivative type only x
exists, the y
would have a value default (probably), there happens the slicing in the b = d
.
In a vector there is an assignment like this. If Vector<Base>
is used when you do v[0] = d
is doing the same as b = d
, occurs the slicing. In each variable of v
only room for the type Base
, I mean, there’s only room for one int
, when you try to put a type that is considered compatible there but it has more data, these will be discarded, then the d
who had two int
you will lose the second.
That is why it is recommended to avoid the use of types per value unless there are clear gains, are obviously basic values immutable or you need a lot of optimization and know a lot what you are doing and understand all the phenomena that can occur, among them the "quartering" (the term should not be slashing?).
When you wear one type by reference or deals with one type per value as reference the problem does not occur because of the indirect.
In these types the basic stored value is a pointer always the same size, never occurs the slicing. The die really is somewhere else and can be different sizes. Of course in completely strong typing languages all will be of the same basic type (without covariance can leak).
Remembering that there are several forms of assignment (copy), one of them is to pass a data to a function. When it is passed by reference the copy is only of the pointer and not of the object itself, then we can say that there is a change and not a copy. Only the copy of the object can shred it.
Another way to solve this is to create a copy builder that deals with the issue properly, but does not always compensate.
Note that this case I exemplified is not a real problem because the compiler does not let it. Even in C++ in the way you do it doesn’t have to go wrong. Now what can go wrong and you realize too late:
struct A {
A(int a) : a_var(a) {}
int a_var;
};
struct B : public A {
B(int a, int b) : A(a), b_var(b) {}
int b_var;
};
B &getB() { //importante o retorno por referência
static B b(1, 2);
return b;
}
int main() {
A a(3);
a = getB();
// a.a_var == 1, b.b_var não copiado para a
B b2(3, 4);
A &a2 = b2;
a2 = getB();
cout << b2.a_var << b2.b_var; //dá 1 e 4, misturou os objetos
}
I put in the Github for future reference.
Wikipedia.
Most languages do not suffer from this. C++ is too high and too low a level, this combination causes the problem. The slicing occurs in several languages, but the compiler identifies and prohibits.
I did not want to go into details there, the question is very pertinent here, I will explain better the phenomenon.
– Maniero