1. This is not object slicing:
base *b = new derived;
This is assigning a pointer of type base to an instance of derived.
One (very common) example of this in action is in callbacks. Consider this:
class Observer
{
public:
virtual void OnEvent() = 0;
};
class Subject
{
public:
Subject() : observer(0) {}
void SetObserver(Observer* o) { observer = o; }
void FireEvent() { if(observer != 0) observer->OnEvent(); }
private:
Observer* observer;
};
class MyObserver : public Observer
{
public:
void OnEvent() { ::printf("Hi there!\n"); }
};
int main()
{
Subject s;
MyObserver o;
s.SetObserver(&o);
s.FireEvent();
return 0;
}
This should be the expected output:
Hi there!
Notice what is happening here. We're passing in a pointer to an instance of MyObserver to SetObserver() even though the function only accepts pointers of type Observer. This works because MyObserver (publicly) derives from Observer. In this case, we say that MyObserver is-an Observer.
The Observer type defines a pure virtual function (The =0 means that the function is pure; it must be implemented by derived classes). The virtual keyword tells the compiler that calling the function should cause the most-derived function to be executed. The OnEvent() function in MyObserver is the most-derived, therefore, that version is called, even though we are calling OnEvent() on a pointer of type Observer.
We go through the trouble of doing all this because in this code Subject doesn't have to know the exact type of its observer - the observers just have to derive from Observer and the Subject instance will call the most derived type's implementation of OnEvent(). This allows for code decoupling - Subject doesn't depend on MyObserver, and MyObserver doesn't depend on Subject.
2. There's nothing wrong with casting a pointer from a base to derived type per se. The following is in fact legal and guaranteed to work:
class Base {};
class Derived : public Base {};
int main()
{
Derived d;
Base* bp = &d;
Derived* dp = static_cast<Derived*>(bp);
return 0;
}
The line before the return statement in this snippet, however, is undefined:
class Base {};
class Derived1 : public Base {};
class Derived2 : public Base {};
int main()
{
Derived1 d1;
Base* bp = &d1;
Derived2* d2p = static_cast<Derived2*>(bp); // WTF?!
return 0;
}
The value of the d2p pointer is meaningless, and attempting to access anything in it will certainly cause a crash, because the bp pointer doesn't actually point to a Derived2 instance, it points to a Derived1 instance. Compilers cannot catch this at compile time, because both Derived1 and Derived2 inherit from Base, so the cast successfully compiles. This is the main danger with casting from a base to a derived type - you won't know until runtime if the cast actually returns meaningful results.
Of course, unless you use dynamic_cast<>(), but the cast incurs a runtime penalty. static_cast<>() involves at most, pointer arithmetic. reinterpret_cast<>() forces a pointer to take on a different (potentially unrelated) type, without performing any pointer arithmetic. This makes reinterpret_cast<>() one of the more dangerous casts and should be used only when necessary, especially if static_cast<>() can do the job.
3. Consider the following:
class Base
{
public:
void Foobar() { ::printf("In Base!\n"); }
};
class Derived : public Base
{
public:
void Foobar() { ::printf("In Derived!\n"); }
};
int main()
{
Derived d;
Derived* dp = &d;
Base* bp = dp;
dp->Foobar();
bp->Foobar();
return 0;
}
If the Foobar() function is not virtual, then you will get this output:
In Derived!
In Base!
Otherwise, if the Foobar() function is virtual, then you will get this output:
In Derived!
In Derived!
To guarantee that a call to the virtual function Foobar() invokes the base implementation via the base pointer, then you have to use the scope resolution operator:
// Prints "In Base!", even if bp actually points
// to an instance of Derived overriding Foobar().
bp->Base::Foobar();