2013-09-21 4 views
2

Предположим, мы имеем следующие файлы (взято из языка ++ Программирование B.Stroustup C):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]; 
} 

Я не понимаю почему объявление/определение (?) класса Overflow {} в stack.h также должно быть записано в 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; 
} 

я компилировать код с: г ++ main.cpp -o stack.cpp Основной

г ++ i686-яблонь darwin11-llvm-g ++ - 4.2 (GCC) 4.2.1 (основано на Apple Inc. build 5658) (LLVM build 2336.11.00)

UPDATE (решение)

Попробовав г ++ (Ubuntu/Linaro 4.7.3-1ubuntu1) 4.7.3 код дал мне об ошибке: stack.cpp: 7: 9: ошибка: переопределение «Класс Stack :: Overflow». Это, конечно, правильно.

Основная информация: предыдущая версия g ++ на mac имеет ошибку.

+0

Выглядит странно. –

ответ

1

Потому что без него не было бы определения Overflow в stack.cpp, и вы не могли использовать этот класс, например, в throw Overflow();.

Общепринятой практикой является предоставление интерфейсов клиенту через файл заголовка, а затем включение этого же заголовка в файл реализации. Если бы мы сделали это в этом (довольно необычном) случае, нам также нужно было бы разоблачить детали реализации (max_size, v[] и top). Повторное определение класса позволяет избежать этого, поэтому детали реализации могут быть скрыты от кода клиента. Это не ошибка для нескольких разрывов классов, при условии, что они являются indentical токеном с помощью токена и не присутствуют в одной и той же единицы перевода.

EDIT: Вопрос был отредактирован - теперь есть #include "stack.h" в stack.cpp, которого ранее не было.

Это делает программу плохо сформированной - в той же единице перевода есть два определения класса Overflow (помните, что включить директиву в основном просто копировать содержимое файла заголовка). Это по сути то же самое, как если бы вы сделали это:

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

Тот факт, что вы можете иметь несколько определений класса по всей программе на самом деле исключение из One Definition Rule.

+0

Я считаю, что это немного вводит в заблуждение, чтобы определить класс в интерфейсе, а не объявлять его. – Tim

+0

@ Подождите секунду, вы отредактировали вопрос и поместили 'include 'stack.h" в исходный файл? – jrok

+0

Да, я положил #include "stack.h" в stack.cpp – Tim

Смежные вопросы