I'm trying to implement a Visitor Pattern in c++, but I'm having problems with the elements being visited in turn having their children visited. For example I have a class Element, which has a vector of Nodes (can be elements or any classes that inherit from node):

class Element : public Node{
	public:
		Element();
		Element(string n, string v = " ");
		~Element();
		void Accept(Visitor& v);
		vector<Node*> nodeVec;
		vector<Attr*> attrVec;
	private:
		string name, value;
};

void Element::Accept(Visitor& v)
{
	v.VisitElement(*this);
}

And I have a concreteVisitorA class, which inherits from an abstract visitor class

class ConcreteVisitorA : public Visitor {
	public:
		ConcreteVisitorA();
		~ConcreteVisitorA();
		void VisitElement(Element e);
};

void ConcreteVisitorA::VisitElement(Element e)
{
	int numNodes = e.GetNumNodes();
	int numAttrs = e.GetNumAttrs();
	cout << "Visitor has found " << numNodes << " noes\n";
	e.nodeVec[0]->Accept(this);
		
	}

The problem is when it gets to the last line of VisitElement, where the first member of the vector is visited i get the error

concreteVisitorA.cc:20: error: no matching function for call to 'Node::Accept(ConcreteVisitorA* const)'
node.h:9: note: candidates are: virtual void Node::Accept(Visitor&)

The Accept method has to have visitor passed to it by reference, because it is abstract. But "this" is a pointer and the whole thing craps out. Any suggestions?

may be u can do it as

void ConcreteVisitorA::VisitElement(Element e)
{
 
	int numNodes = e.GetNumNodes();
	int numAttrs = e.GetNumAttrs();
	cout << "Visitor has found " << numNodes << " noes\n";


              Visitor tempV;/*set all the necessary data members*/
	e.nodeVec[0]->Accept(tempV);
		
}

Thanks for the reply. The problem with that is it needs to be a single Visitor object which "visits" every element.

So ConcreteVisitorA VisitorA
will have a stack, list, vector, or something and with each visit it will store information about the element it visited.
So it has to be "this" which gets passed to it, as the one instance of the class must be the one to visit it.

I simply added another implementation of accept, which could take take a pointer and now it works.

void Element::Accept(Visitor& v)
{
	v.VisitElement(*this);
}
void Element::Accept(Visitor* v)
{
	v->VisitElement(*this);
}

I simply added another implementation of accept, which could take take a pointer and now it works.

void Element::Accept(Visitor& v)
{
	v.VisitElement(*this);
}
void Element::Accept(Visitor* v)
{
	v->VisitElement(*this);
}

wel done. Its because a base class pointer can point to a derived class object also.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.