Given that we have defined three functions that are common to all
interfaces, perhaps we should hoist them into an interface that is
the base for every other. This technique enables a client to rely on
this behavior in any interface. It can also act as a signature
interface.
Let's redefine our interfaces as
Header file istring.h.
struct
IAnyInterface { virtual void *DynamicCast(const char
*psz)=0; virtual void DuplicatePointer()=0; virtual void
DestroyPointer()=0; };
struct IString : public
IAnyInterface { virtual const char*Find(const char
*psz)=0; virtual int Length()=0; };
struct IString2 :
public IMyString { virtual const
char*Reverse()=0; };
struct IPersist : public
IAnyInterface { virtual void Save(const char
*psz)=0; virtual void Load(const char *psz)=0; };
The Dynamic_cast() function changes slightly. Notice that we
cannot static_cast<> to
IAnyInterface * because CMyString derives from multiple interfaces,
all of which derive from IAnyInterface. It would be ambiguous. Which
"IAnyInterface-ness" of the object would the compiler choose, that
evident in the "Persistent-ness" of the object or that evident in
the "IString(2)-ness" of the object?
Source file mystring.cpp.
void *
CMyString::Dynamic_cast(const char *psz) {
void *pret = NULL; if
(strcmp(psz,"IString")==0||strcmp(psz,"IAnyInterface")==0)
pret = (void *)static_cast<IString
*>(this); else if
(strcmp(psz,"IString2")==0)
pret = (void *)static_cast<IString2
*>(this); else if
(strcmp(psz,"IPersist")==0)
pret = (void *)static_cast<IPersist
*>(this); if
(NULL!=pret)
((IAnyInterface
*)pret)->DuplicatePointer(); return
pret; }
If you would like to write some code to try this out, click here.
Next
we will look at some of the shortcomings of the technique we have
just developed and some of the problems we did not solve.

|