У меня есть класс Angle с оператором overloaded < < и двумя файлами cpp, в которые включен заголовочный файл. У меня есть инструкция #ifndef, чтобы предотвратить включение файла несколько раз. Однако кажется, что он включен несколько раз, так как я получил ошибку, которую оператор < < был определен несколько раз. Затем я добавил приложение #warning, чтобы увидеть, когда этот файл включен. В выводе компилятора видно, что #warning обрабатывается дважды. Если я переведу определение в файл cpp, он, очевидно, работает, но я по-прежнему считаю поведение в этом случае странным.Файл заголовка включен дважды, несмотря на #ifndef
По-моему, компилятор не должен обрабатывать файл заголовка дважды. Есть ли причина такого поведения?
main.cpp
#include <iostream>
#include <cmath>
#include <cstdlib>
#include "Angle.h"
using namespace std;
int main() {
Angle a = (Angle)(M_PI/4);
cout << a << endl;
return EXIT_SUCCESS;
}
Angle.h
#ifndef ANGLE_ANGLE_H
#define ANGLE_ANGLE_H
#include <iostream>
class Angle {
private:
double value;
public:
explicit Angle (double value) {this->value = value; }
double getValue() const {return this->value;}
// Operators
operator const double() const {
return this->value;
}
};
#warning INCLUDING_ANGLE_H
std::ostream& operator << (std::ostream& os, const Angle& obj){
os << obj.getValue();
return os;
}
#endif //ANGLE_ANGLE_H
Angle.cpp
#include "Angle.h"
Я компиляции с followi Команда нг:
g++ main.cpp Angle.cpp -o angle
со следующей ошибкой:
In file included from main.cpp:5:0:
Angle.h:19:2: warning: #warning INCLUDING_ANGLE_H [-Wcpp]
#warning INCLUDING_ANGLE_H
^
In file included from Angle.cpp:1:0:
Angle.h:19:2: warning: #warning INCLUDING_ANGLE_H [-Wcpp]
#warning INCLUDING_ANGLE_H
^
/tmp/cci53Hrd.o: In function `operator<<(std::ostream&, Angle const&)':
Angle.cpp:(.text+0x0): multiple definition of `operator<<(std::ostream&, Angle const&)'
/tmp/ccBbwtlD.o:main.cpp:(.text+0x0): first defined here
collect2: error: ld returned 1 exit status
Это хорошее время, чтобы прочитать на "перевода единиц" и, как C++ код на самом деле скомпилирован. В принципе, каждый .cpp-файл скомпилирован независимо, тогда линкера отвечает за совпадение функций * определений * (которые обычно могут выполняться только один раз) с их * обычаями *, которые скомпилированы на основе соответствующих * деклараций *. – Cameron
См. Также: http: // stackoverflow.com/questions/14425262/why-include-guard-do-not-prevent-multiple-function-определения – chris