I can do this
extern 开发者_开发百科int i;
extern int i;
But I can't do the same with a class
class A {
..
}
class A {
..
}
While in both cases no memory is being allocated.
The following are declarations:
extern int i;
class A;
And the next two are definitions:
int i;
class A { ... };
The rules are:
- a definition is also a declaration.
- you have to have 'seen' a declaration of an item before you can use it.
- re-declaration is OK (must be identical).
- re-definition is an error (the One Definition Rule).
The closest equivalent to extern int i
with a class is a forward declaration, which you can do as many times as you like:
class A;
class A;
class A;
class A{};
When you define the actual class you are saying how much memory is required to construct an instance of it, as well as how that memory is laid out. That's not really the issue here, though.
The first (extern) makes a reference to an existing variable. So you are just indicating the variable twice.
The class declaration gives meaning to a type (your class: A). You are trying to give two meanings to A. This is not of any use for you, and can only confuse, so the compiler protects you from it.
Btw, if you put both classes in difference namespaces you can give them the same name.
You can declare a class and an object multiple times, what you can't do is define it more than once.
extern
makes this a declaration and not a definition (because there is no initializer):
extern int a;
The body makes your class
a definition and not just a declaration. You can define a class once.
you can do
class A;
as often as you want and then in one file define it with
class A { ... }
Example for this:
classB.h:
class A;
class B { A *a; }
classA.h:
class B;
class A { B *b; }
But in the first case ther is no contradiction.
extern int i;
extern double i;
won't work either. So if you create class A to times it wouldn't be possible to decide who A is.
I guess the real question is 'why would you want to?'. The situation sometimes arises when you include a header file multiple times in the same translation unit (.cpp file). If this is the case, you should look at using include guards to keep the compiler happy.
Another reason that this might be causing problems for you is that you're using a 3rd-party library which defines classes whose names conflict with your own classes. In this case you should look at using namespaces to resolve the ambiguity.
In both cases 'extern int i;' is referencing the same object (declared elsewhere) and so the multiple declarations are unambiguous. If you wrote:
extern int i;
extern float i;
The compiler would complain about the ambiguity (because it wouldn't know which variable you intended to manipulate if you wrote 'i=0;'.
Duplicate class declarations gives rise to the possibility that declarations are different; again, how would the compiler know which one to use when it encounters 'A foo;'? I guess the compiler could compare the class declarations and verify that they're infact identical, but this would be an awful lot of effort to go to when the alternative solutions (namespaces, include guards, renaming) are so much easier (and probably less confusing for whoever ends up reading the code).
It has nothing to do with declarations vs definitions. The issue is types versus objects.
extern int i;
tells the program that at an object of type int
exists, and its name is i
. Because it is extern
no storage is allocated for it here, but somewhere else, probably in another translation unit, it is defined and storage is allocated for it.
class A {
..
};
defines a type named A
. It doesn't allocate any objects or variables. It makes absolutely no difference at runtime, and no storage is allocated for it, because it is not an object. It simply introduces a new type to the compiler. From this point on, you are able to create objects of type A
, and they will have storage allocated for them.
I gave it some thought. I realized class in not a data type, it is a enabler for defining a data type.
So in
extern int i;
extern int i;
int is a data type. So we are re-declaring a variable not a data type.
But in
class A {...};
class A {...};
A is a data type. And we are re-defining a data type, which is not allowed, of course.
精彩评论