void
; for rare cases it can be a more specific type. For polymorphism, refer to the objects using pointers (void*
) .
NOTE Because it is contrary to the normal style rules,
you should not use a pointer to pass an argument to a method that is not going to alias or own the argument. But, because void&
is illegal in C++, you must use void*
in all such cases--even though the method is not going to alias or own the argument.
An implementation class does not have enough information to perform type-specific operations, so it delegates these operations to a specialized class. The specialized class' methods cast the void*
arguments back to the correct type and perform the type-specific operation. Because these casts are blind casts, the object must always be cast to and from the same type. If you pass in the object as a base class, but extract it as a derived class, the C++ compiler will not perform the pointer fix-up, and you will end up with an incorrect pointer value.
class TBase { ... }; class TDerived : public TBase, virtual public VVirtual { ... }; void FunctionTakingTBaseAsVoid(void* item); void f() { TBase base; TDerived derived; FunctionTakingTBaseAsVoid(item); // Correct FunctionTakingTBaseAsVoid(d&erived); // Incorrect FunctionTakingTBaseAsVoid((TBase*) &derived); // Correct } void FunctionTakingTBaseAsVoid(void* item) { TBase* asBase = (TBase*) item; // Correct TDerived* asDerived = (TDerived*) item; // Incorrect TDerived* asDerived = (TDerived*) (TBase*) item; // Correct, conditionally }
void
objects; however, the delete
operator is the one exception. Deleting a pointer to an object that is held as a void*
silently releases the storage that the object occupies, but does not call that object's destructor.
{ void* baseAsVoid = new TBase(...); delete baseAsVoid; // Incorrect. Destructor not called. TBase* base = (TBase*) baseAsVoid; delete base; // Correct }