Why can't I forward-declare a class in a namespace using double colons?
class Namespace::Class;
Why do I have to do this?:
namespace Namespace {
class Class;
}
Using VC++ 8.0, the compiler issues:
error C2653: 'Namespace' : is not a class or namespace name
I assume that the problem here is that the compiler cannot tell whether Namespace
is a class or a namespace? But why does this matter since it's just a forward declaration?
Is there another way to forward-declare a class defined in some namespace? The syntax above feels like I'm "reopening" the namespace and extending its definition. What if Class
were not actually defined in Namespace
? Would this result in an error at some point?
You're getting correct answers, let me just try re-wording:
class Namespace::Class;
Why do I have to do this?
You have to do this because the term Namespace::Class
is telling the compiler:
...OK, compiler. Go find the namespace named Namespace, and within that refer to the class named Class.
But the compiler doesn't know what you're talking about because it doesn't know any namespace named Namespace
. Even if there were a namespace named Namespace
, as in:
namespace Namespace
{
};
class Namespace::Class;
it still wouldn't work, because you can't declare a class within a namespace from outside that namespace. You have to be in the namespace.
So, you can in fact forward declare a class within a namespace. Just do this:
namespace Namespace
{
class Class;
};
Because you can't. In C++ language fully-qualified names are only used to refer to existing (i.e. previously declared) entities. They can't be used to introduce new entities.
And you are in fact "reopening" the namespace to declare new entities. If the class Class
is later defined as a member of different namespace - it is a completely different class that has nothing to do with the one you declared here.
Once you get to the point of defining the pre-declared class, you don't need to "reopen" the namespace again. You can define it in the global namespace (or any namespace enclosing your Namespace
) as
class Namespace::Class {
/* whatever */
};
Since you are referring to an entity that has already been declared in namespace Namespace
, you can use qualified name Namespace::Class
.
I suppose it's for the same reason you cannot declare nested namespaces in one go like this:
namespace Company::Communications::Sockets {
}
and you have to do this:
namespace Company {
namespace Communications {
namespace Sockets {
}
}
}