Click here to Skip to main content
15,884,425 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hello,

I have a base class for a record, and want to add additional fields using decorators, and be able to chain the decorators (records can have an email, or a date of birth, or both, or none). I'm also going to have a lot of such decorators; one for each addtional field, and its comparison function. Once this is done, I'm going to add the objects to a vector, using a base class pointer.

Here's a precis of the code:

C++
class BaseRecord
{
public:
	virtual bool Compare();		// defined elsewhere

protected:
	std::string m_strName;
	std::string m_strAddress:
};

class EmailDecorator : public BaseRecord
{
public:
	EmailDecorator(BaseRecord *pBase) : m_pBase(pBase){}

	bool Compare()
	{
		if (!CompareEmail())		// defined elsewhere
		{
			return false;
		}

		return m_pBase->Compare();
	}

protected:
	std::string m_strEmail

private:
	BaseRecord *m_pBase;
};

class DOBDecorator : public BaseRecord
{
public:
	DOBDecorator(BaseRecord *pBase) : m_pBase(pBase){}

	bool Compare()
	{
		if (!CompareDOB())		// defined elsewhere
		{
			return false;
		}

		return m_pBase->Compare();
	}

protected:
	std::string m_strDOB;

private:
	BaseRecord *m_pBase;
};


Those are the classes. I then want to do the following:

C++
vector<BaseRecord *> m_vecRecords;

BaseRecord *pRecord = new BaseRecord();

// below is incorrect - copies only the pointer to the vector
m_vecRecords.push_back(pRecord);

// this is OK - default copy constructor used for BaseRecord
m_vecRecords.push_back(new BaseRecord(*pRecord));

// now chain the decorators

// pRecord is a BaseRecord
BaseRecord *pRecord = new EmailDecorator(pRecord);

// this is again incorrect - copies only pointer to the vector
m_vecRecords.push_back(pRecord);

// ??? what to do here - needs copy constructor for EmailDecorator
m_vecRecords.push_back(new EmailDecorator(*pRecord));

// pRecord is an EmailRecord
BaseRecord *pRecord = new DOBDecorator(pRecord);

// this is again incorrect - copies only pointer to the vector
m_vecRecords.push_back(pRecord);

// ??? what to do here - needs copy constructor for DOBDecorator
m_vecRecords.push_back(new DOBDecorator(*pRecord));

// Attempts at writing copy constructors

// should p be an EmailDecorator *p, or a BaseRecord *
EmailDecorator::EmailDecorator(const EmailDecorator *p)
{
// this wuill leak - no delete in the destructor
// in fact, there is no destructor
m_pBase = new BaseRecord(p);
m_strEmail = p->m_strEmail;
}

// should p be a DOBDecorator *, or  BaseRecord *
// in the above example, when the copy constructor is needed, it is an EmailRecord *
DOBDecorator::DOBDecorator(const DOBDecorator *p)
{
// this will leak - no delete in the destructor
// in fact, there is no destructor
m_pBase = new BaseRecord(p);
m_strDOB = p->m_strDOB;
}


So how do I write copy constructors for my decorators? It would appear that there must be a way to do what I want without even needing copy constructors.

Thanks for reading this. Any advice would be much appreciated.

Andy
Posted
Comments
[no name] 10-Apr-14 12:06pm    
You keep re-using the variable 'pRecord' which tells me this code won't compile.

1 solution

I think you can use the virtual constructor idiom as described here: http://www.parashift.com/c++-faq-lite/virtual-ctors.html[^].

But then again i dont really see whats wrong with storing the pointer as you've mentioned (despite the fact that you shouldn't store a raw pointer but rather a std::unique_ptr or if needed a std::shared_ptr )
C++
// pRecord is a BaseRecord
BaseRecord *pRecord = new EmailDecorator(pRecord);
 
// this is again incorrect - copies only pointer to the vector
m_vecRecords.push_back(pRecord);
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900