TITLE: Example of another downcasting scheme

PROBLEM: lowry@watson.ibm.com (Andy Lowry), 29 Mar 93

I have just learned, the hard way, one of the dangers of using virtual
base classes, i.e., that one cannot cast an A* to a B* if A is a
virtual base class of B.  

RESPONSE:maxtal@extro.ucc.su.OZ.AU (John MAX Skaller), 30 Mar 93

	No, the base classes have learned they are in danger of
being abused, and have got some virtual for protection!

	This is not a danger of using virtual bases. What 
is dangerous and usually bad design is downcasting.


RESPONSE: jimad@microsoft.com (Jim Adcock), 31 Mar 93
	  Microsoft Corporation

Below find a cartoon example of how to use a home-brew RTTI to do
downcasting from a virtual base.  Of course, if a bolt of lightning
should come out of the heavens and strike you down, I can accept no
responsibility for your choices....

#include <iostream.h>

class A
{
	int amember;
public:
	A() { amember = 123; }
	void print() { cout << amember << ' '; }
	virtual void* dyncast(char toTypeName);
};

void* A::dyncast(char toTypeName)
{
	if (toTypeName != 'A')
		return 0;
	else
		return this;
}

class B : public virtual A
{
	float bmember;
public:
	B() { bmember = 3.14; }
	void print() { A::print(); cout << bmember << ' '; }
	virtual void* dyncast(char toTypeName);
};

void* B::dyncast(char toTypeName)
{
	if (toTypeName != 'B')
		return A::dyncast(toTypeName);
	else
		return this;
}

class C : public virtual A
{
	double cmember;
public:
	C() { cmember = 1.0/3.0; }
	void print() { A::print(); cout << cmember << ' '; }
	virtual void* dyncast(char toTypeName);
};

void* C::dyncast(char toTypeName)
{
	if (toTypeName != 'C')
		return A::dyncast(toTypeName);
	else
		return this;
}


class D : public B, public C
{
	char* dmember;
public:
	D() { dmember = "dmember"; }
	void print() { B::print(); C::print(); cout << dmember << ' '; }
	virtual void* dyncast(char toTypeName);
};

void* D::dyncast(char toTypeName)
{
	void* p;
	if (toTypeName != 'D')
	{
		if (p = B::dyncast(toTypeName))
			return p;
		else
			return C::dyncast(toTypeName);
	}
	else
		return this;
}

main()
{
	A* pa = new D;
	if (pa) { pa->print(); cout << '\n'; }
	else cout << "pa is null!\n";

	B* pb = (B*) (pa->dyncast('B'));
	if (pb) { pb->print(); cout << '\n'; }
	else cout << "pb is null!\n";

	C* pc = (C*) (pb->dyncast('C'));
	if (pc) { pc->print(); cout << '\n'; }
	else cout << "pc is null!\n";

	D* pd = (D*) (pc->dyncast('D'));
	if (pd) { pd->print(); cout << '\n'; }
	else cout << "pd is null!\n";

	void* pe = (void*) (pd->dyncast('E'));
	if (pe) { cout << "must be a bug!\n"; }
	else cout << "pe is null!\n";

	return 0;
}



