<source lang="cpp">
#include <iostream>
{
public:
virtual void make_sound() const = 0; ▼
virtual ~Animal() = default;
▲ virtual void make_soundMakeSound() const = 0;
};
class dogDog : public animalAnimal {
public:
{
virtual void make_soundMakeSound() const override { std::cout << "woof!" << std::endl; }
{
std::cout << "woof!" << std::endl;
}
};
class null_animalNullAnimal : public animalAnimal {
public:
{
virtual void make_soundMakeSound() const override { }
};
</source>
Here, the idea is that there are situations where a pointer or reference to an <code>animalAnimal</code> object is required, but there is no appropriate object available. A null reference is impossible in standard-conforming C++. A null <code>animal Animal*</code> pointer is possible, and could be useful as a place-holder, but may not be used for direct dispatch: <code>a->make_soundMakeSound()</code> is undefined behavior if <code>a</code> is a null pointer.
The null object pattern solves this problem by providing a special <code>null_animalNullAnimal</code> class which can be instantiated bound to an <code>animalAnimal</code> pointer or reference.
The special null class must be created for each class hierarchy that is to have a null object, since a <code>null_animalNullAnimal</code> is of no use when what is needed is a null object with regard to some <code>widgetWidget</code> base class that is not related to the <code>animalAnimal</code> hierarchy.
Note, that NOT having a null class at all is an important feature, in contrast to languages where "anything is a reference" (e.g. Java and C#). In C++, the design of a function or method may explicitly state whether null is allowed or not.
<source lang="cpp">
// functionFunction which requires an animal|Animal| instance, and will not accept null.
void DoSomething(const Animal& animal) {
// and will not accept null
void do_something( const// |animal&| Instmay )never {be null here.
// Inst may never be null here
}
// functionFunction which may accept an animal|Animal| instance or null.
void do_somethingDoSomething( const animalAnimal* pInst animal) {
// pInst|animal| may be null.
}
</source>
|