C ++双重声明/定义?

时间:2013-09-21 08:32:37

标签: c++ exception declaration

假设我们有以下文件(取自B.Stroustup的C ++编程语言):

stack.h

namespace Stack{
    void push(int);
    int pop();
    class Overflow{};
}

stack.cpp

#include "stack.h"

namespace Stack{
  const int max_size = 1000;
  int v[max_size];
  int top;
  class Overflow{};
}

void Stack::push(int elem){
  if(top >= max_size){
    throw Overflow();
  }
  v[top++] = elem;
}

int Stack::pop(){
  if(top <= 0){
    throw Overflow();
  }
  return v[--top];
}

我不明白为什么stack.h中的类Overflow {}的声明/定义(?)也必须用stack.cpp编写?

编写此类代码是否正确?

更新

的main.cpp

#include <iostream>
#include "stack.h"

using namespace std;

int main(){
  try{
    int a = 0;
    while(true){
      Stack::push(a++);
    }
  } catch(Stack::Overflow){
    cout << "Stack::Overflow exception, YEAH!" << endl;
  }

  return 0;
}

我用以下代码编译代码: g ++ main.cpp stack.cpp -o main

g ++ i686-apple-darwin11-llvm-g ++ - 4.2(GCC)4.2.1(基于Apple Inc. build 5658)(LLVM build 2336.11.00)

更新(解决方案)

尝试 g ++(Ubuntu / Linaro 4.7.3-1ubuntu1)4.7.3 代码给了我一个错误:stack.cpp:7:9:错误:重新定义'class Stack ::溢出'。这当然是正确的。

总结:之前提到的mac上的g ++版本有一个错误。

1 个答案:

答案 0 :(得分:1)

因为没有它,stack.cpp中就没有Overflow的定义,你也无法使用该类,例如在throw Overflow();中。

通常的做法是通过头文件将接口暴露给客户端,然后在实现文件中包含相同的头。如果我们在这个(相当不寻常的)情况下这样做,我们还需要公开实现细节(max_sizev[]top)。重复的类定义是为了避免这种情况,因此可以从客户端代码中隐藏实现细节。如果它们是令牌的缩进令牌并且不存在于同一个翻译单元中,则具有多个类定义并不是错误。

编辑:问题已被修改 - 现在stack.cpp中有#include "stack.h"以前没有。

这使得程序格式错误 - 在同一翻译单元中有两个类Overflow的定义(请记住,include指令基本上只是复制粘贴头文件的内容)。它本质上就像你这样做:

int i;
int i; // error: redefinition of i
int main() {}

事实上,您可以在整个程序中拥有多个类的定义,这实际上是One Definition Rule的一个例外。