Reputation: 16121
I want to implement the Visitor pattern in C++ like this:
class Visitor{
public:
virtual ~Visitor();
virtual void visit(C & t)=0;
};
class V : public Visitor{
public:
void visit(C &c);
};
class C{
public:
void accept(Visitor &v){ v.visit(*this); }
};
But the compiler complains abount 2 syntax errors: Unknown identifier C and Visitor. Where is the problem?
Upvotes: 1
Views: 812
Reputation: 114599
In the C++ language the compiler will not look ahead for names that are yet to be defined or, to say it better, sometimes it does and sometimes it doesn't.
You can say for example
struct Foo
{
Foo(int x) : m_x(x) { }
int m_x;
};
and the compiler will not complain even if you used m_x
before defining what m_x
is, but however at the module level this look ahead is not present:
struct Foo
{
Bar *p; // Error, Compiler doesn't know what Bar is
};
// Too late, the compiler is not going to read down here while
// analyzing Foo.
struct Bar
{
int x;
};
How do you solve cases in which you need to use something before defining it? By using a special "forward declaration", in which you only state that there will be something with that name and you define later what it is in the specific... for example
struct Foo; // There will be a struct Foo defined somewhere
struct Bar
{
Foo *p; // Fine, even if the compiler doesn't really know Foo
};
struct Foo
{
Bar *q; // Fine and no forward needed... Bar is known at this point
};
More or less the rule is: in a single class all methods can see all other methods and all members even if they are defined later in the class, at a module level instead every name must be known before it can be used.
Sometimes a more complex pattern is needed, like
struct Foo;
struct Bar
{
void doit(Bar x);
};
struct Foo
{
void doit_too(Foo x);
};
void Foo::doit(Bar x) { ... }
void Bar::doit_too(Foo x) { ... }
In the last case you are forced to put the implementation of both methods after the declarations of both classes because just knowing that Foo
is a class is not enough to be able to compile a copy operation (note the parameter in the methods has been passed by value, not by pointer or reference).
Upvotes: 5
Reputation: 3443
Problem is Class C is not defined at the point Visitor uses it. Either move it to the top (class C that is) or:
class C;
Add the above forward declaration at top of file. Since you only use it as a reference param, this should suffice.
Upvotes: 3
Reputation: 22644
At the fourth line, nobody knows what C
is. It is an unknown identifier.
This makes the definition of Visitor
not valid, hence when you try to use your Visitor
later another error occurs.
Upvotes: 3
Reputation: 8604
At the moment the compiler sees
virtual void visit(C & t)=0;
name C
is unknown.
You need to forward-declare class C
before Visitor
class C;
class Visitor{
...
}
Upvotes: 5