2010-02-04 89 views
7

我能做到这一点为什么我不能多声明一个类

extern int i; 
extern int i; 

不过虽然在这两种情况下没有记忆是暂时我不能做同样的一类

class A { 
.. 
} 
class A { 
.. 
} 

分配。

+0

它们应该是两个不同的类吗?或部分班? – Naveen 2010-02-04 08:48:49

+0

@all 其实我的理解是定义和声明之间的区别事实是 - 后者没有分配内存。这就是为什么我认为A类{..}更多是一个声明而不是一个定义。 – deeJ 2010-02-04 09:30:48

回答

25

以下是声明

extern int i; 
class A; 

而接下来的两个是定义

int i; 
class A { ... } 

的规则是:

  • 的定义也是声明。
  • 在使用它之前,您必须已经“看到”一个项目的声明。
  • 重新声明是可以的(必须是相同的)。
  • 重新定义是一个错误(一个定义规则)。
+0

你说得好。我撤回我的回答 – 2010-02-04 08:56:12

+3

对于它的价值,这被称为一个定义规则。 – GManNickG 2010-02-04 08:58:59

+6

您可以添加 “A级”; 事实上,是类A的声明。 – Klaim 2010-02-04 08:59:11

2

第一个(extern)引用了现有的变量。所以你只是指出了两次变量。

类声明给出了一个类型(你的类:A)的含义。你试图给A两个含义。这对你没有任何用处,只能混淆,所以编译器可以保护你。

顺便说一句,如果你把两个类放在不同的命名空间中,你可以给它们相同的名字。

0

但在第一种情况下,这并不矛盾。

extern int i; 
extern double i; 

也不起作用。 因此,如果您创建A级时间,则无法确定A是谁。

3

最接近相当于extern int i一类是正向的声明,这是你喜欢,你可以做很多次:

class A; 

class A; 

class A; 

class A{}; 

当你定义的实际类,你说多少内存需要构建它的一个实例,以及如何布置这些内存。虽然这不是真正的问题。

1

你可以做

class A; 

经常只要你想,然后在一个文件中与

class A { ... } 

实例把它定义为这样:
classB.h:

class A; 
class B { A *a; } 

classA。H:

class B; 
class A { B *b; } 
+0

这是行不通的:编译器需要看'B'的定义来计算'A'的大小。尽管如此,指针或引用仍然可以正常工作。 – 2010-02-04 09:12:52

+0

@roger:谢谢,纠正。我的C++知识有点生疏 – dbemerlin 2010-02-04 09:35:01

1

可以声明类和对象多次,你不能做的就是定义不止一次。

extern使这是一个声明,而不是定义(因为没有初始化):

extern int a; 

的身体,使你的class的定义,而不仅仅是一个声明。你可以定义一个类。

+0

更确切地说,extern是关于链接的。可以用extern定义,如extern int a = 7; – 2010-02-04 09:03:08

+0

是的,但在这种情况下,'extern'更重要的作用是它将声明更改为不是定义。 – 2010-02-04 09:29:11

0

我想真正的问题是'你为什么要?'。当您在同一翻译单元(.cpp文件)中多次包含头文件时,情况有时会出现。如果是这样的话,你应该看看使用include guards来保持编译器的快乐。

这可能会给您带来问题的另一个原因是您使用的第三方库定义了与您自己的类名称冲突的类。在这种情况下,您应该查看使用名称空间来解决歧义。

在这两种情况下'extern int i;'引用同一个对象(在别处声明),因此多个声明是明确的。如果您写道:

extern int i; 
extern float i; 

编译器会抱怨模糊(因为它不知道你打算哪个变量来操作,如果你写了“I = 0;”

复制类的声明引起到声明不同的可能性;再次,编译器在遇到'A foo'时如何知道使用哪一个?'我猜编译器可以比较类声明并验证它们实际上是相同的,但这会是当替代解决方案(命名空间,包括守卫,重命名)变得如此简单(并且可能不会让最终读取代码的人感到困惑)时,可以付出很多努力。

0

它与声明vs定义无关。问题是类型与对象。

extern int i; 

告诉在类型的对象int存在的程序,它的名字是i。因为它是extern没有为它分配存储空间这里是,但是在别的地方,可能在另一个翻译单元中,它被定义并为其分配存储空间。

class A { 
.. 
}; 

限定命名A。它不分配任何对象或变量。它在运行时完全没有区别,并且没有为其分配存储空间,因为它不是一个对象。它只是向编译器引入了一个新的类型。从这一点开始,您可以创建类型为A的对象,而他们将为其分配存储空间

0

我给了它一些想法。我意识到类不是数据类型,它是定义数据类型的推动者。

所以在

extern int i; 
extern int i; 

int是一种数据类型。所以我们重新声明一个不是数据类型的变量。

但在

class A {...}; 
class A {...}; 

A是数据类型。我们正在重新定义一个数据类型,当然这是不允许的。

相关问题