//smart2b.cpp
#include <fstream.h>
#include <string.h>
class String	{
public:
   String(const char* nullStr) : refCount(0)	{
	cout << "\tString::String(), this=" << this << endl;
	len=strlen(nullStr); 	buf=new char[len+1];
	memcpy(buf,nullStr,len); 	buf[len]=0; }
   virtual ~String()	{
	cout << "\tString::~String(), this=" << this << endl;
	delete [] buf;	}
   char* get()	{	return buf;	}
   int ref() const	{	return ++((String*)this)->refCount;	}
   int unRef() const	{	return --((String*)this)->refCount;	}
protected:
   char* buf;	int len;
   int refCount;
};

class StringPtr	{
public:
   StringPtr(String* s)	: str(s)	{
	cout << "\tStringPtr::StringPtr(String*), this=" << this << endl;
	str->ref();	}
   StringPtr(const StringPtr& s) : str(s.str) {
	cout << "\tStringPtr::StringPtr(StringPtr&), this=" << this << endl;
	str->ref(); }
   virtual ~StringPtr()	{
	cout << "\tStringPtr::~StringPtr(), this=" << this << endl;
	if (!str->unRef()) delete str;	}
   String* operator->()	{
	cout << "\tStringPtr::operator->(), this=" << this << endl;
	return str;	};
protected:
   String* str;
};
void main()	{
   cout = *new ofstream("test.txt");
   cout << "constructing str1\n";
   StringPtr str1 = new String("Hello World\n");
   cout << "constructing str2\n";
   StringPtr str2 = str1;
   cout << "constructing str3\n";
   StringPtr str3 = str2;
   cout << str1->get();
	// the three smart pointers will be deleted by the compiler here
   }
/**** output***********
constructing str1
	String::String(), this=0x3f4f0176
	StringPtr::StringPtr(String*), this=0x3f77262e
constructing str2
	StringPtr::StringPtr(StringPtr&), this=0x3f772628
constructing str3
	StringPtr::StringPtr(StringPtr&), this=0x3f772622
	StringPtr::operator->(), this=0x3f77262e
Hello World
	StringPtr::~StringPtr(), this=0x3f772622
	StringPtr::~StringPtr(), this=0x3f772628
	StringPtr::~StringPtr(), this=0x3f77262e
	String::~String(), this=0x3f4f0176
***********************/


