Yes -- a pointer to base
is required to be able to refer to an object of any type derived from base
and still retain the correct type for the derived object (and for what it's worth, the same is true with references).
Pointers and Object slicing
-
31-05-2022 - |
Question
I'm learning the hard way about object slicing, and I'm wondering if it is possible for a pointer to ever be object sliced. In other words:
- Can pointers ever be victims of object slicing or are you always safe from object slicing as long as you're using a pointer?
Solution 2
OTHER TIPS
It depends on how loosely you're willing to define "slicing". In a sense, when you point to a derived object with a base pointer (or reference), any non-virtual functions get sliced. For instance:
class A {
void Print() { cout << "Class A\n"; }
};
class B : public A {
void DoB() {}
void Print() { cout << "Class B\n"; }
};
B b;
A* a = &b;
a->DoB(); // Won't compile!
a->Print(); // Prints "Class A", not "Class B"
The call to DoB
doesn't work because we're using a pointer to an A
, so the compiler doesn't know it can call DoB
on that pointer. In this way, you're losing part of B
, so you can think of this as a form of slicing.
The last line in particular is an example of a phenomenon called "name hiding". Because Print
wasn't declared virtual
in the base class, and our pointer is of type A
, the compiler doesn't know that it should call B::Print
instead of A::Print
.
An important example of this problem comes into play with your destructor:
class A {
~A() {}
};
class B : public A {
std::vector<int> v;
};
A* a = new B;
delete a; // What happens to B::v? Undefined behaviour!
Here, because the destructor wasn't marked as virtual
, it called the base class's destructor in a non-virtual context, which means B
's destructor won't get called.