Подтвердить что ты не робот

Включение файлов .cpp

Я читал в таких местах, как здесь, что вы должны включить файлы .h, а не файлы .cpp, потому что иначе вы получите сообщение об ошибке. Так, например,

main.cpp

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

int main(int argc, char *argv[])
{
int x=42;
std::cout << x <<std::endl;
std::cout << foo(x) << std::endl;
return 0;
}

foop.h

#ifndef FOOP_H
#define FOOP_H
int foo(int a);
#endif

foop.cpp

int foo(int a){
    return ++a;
}

работает, но если я заменю #include "foop.h" на #include "foop.cpp", я получаю сообщение об ошибке (используя Dev С++ 4.9.9.2, Windows):

multiple definition of foo(int)
first defined here

Почему это?

4b9b3361

Ответ 1

То, что include выполняет, копирует все содержимое из файла (это аргумент внутри <> или ""), поэтому, когда препроцессор завершает свою работу, main.cpp будет выглядеть так:

// iostream stuff

int foo(int a){
    return ++a;
}

int main(int argc, char *argv[])
{
   int x=42;
   std::cout << x <<std::endl;
   std::cout << foo(x) << std::endl;
   return 0;
}

Итак, foo будет определен в main.cpp, но определение также существует в foop.cpp, поэтому компилятор "запутывается" из-за дублирования функции.

Ответ 2

Есть много причин препятствовать включению файла .cpp, но это не является строго запрещенным. Ваш пример должен компилироваться.

Вероятно, проблема заключается в том, что вы компилируете как main.cpp, так и foop.cpp, что означает, что две копии foop.cpp связаны между собой. Компилятор жалуется на дублирование.

Ответ 3

Когда вы произнесете #include "foop.cpp", вы скопировали все содержимое foop.cpp и вставили его в main.cpp.

Поэтому, когда вы компилируете main.cpp, компилятор испускает main.obj, который содержит исполняемый код для двух функций: main и foo.

При компиляции foop.cpp сам компилятор испускает foop.obj, который содержит исполняемый код для функции foo.

Когда вы связываете их вместе, компилятор видит два определения для функции foo (один из main.obj, а другой из foop.obj) и жалуется, что у вас несколько определений.

Ответ 4

Это сводится к различию между определениями и декларациями.

  • Вы можете объявлять функции и переменные несколько раз, в разных единицах перевода или в одной и той же единицы перевода. После объявления функции или переменной вы можете использовать ее с этой точки.
  • Вы можете определить нестационарную функцию или переменную только один раз во всех единицах перевода. Определение нестатических элементов более одного раза вызывает ошибки компоновщика.

Заголовки обычно содержат объявления; Файлы cpp содержат определения. Когда вы включаете файл с определениями более одного раза, вы получаете дубликаты во время компоновки.

В вашей ситуации одна дефиниция происходит от foo.cpp, а другое определение происходит от main.cpp, которое включает foo.cpp.

Примечание:, если вы измените foo на static, у вас не будет ошибок связывания. Несмотря на отсутствие ошибок, это не очень хорошо.

Ответ 5

Вы должны просто включить заголовочный файл (ы).

Если вы включаете заголовочный файл, заголовочный файл автоматически находит файл .cpp.  - > Этот процесс выполняется LINKER.

Ответ 6

Поскольку ваша программа теперь содержит две копии функции foo, один раз внутри foo.cpp и один раз внутри main.cpp

Подумайте о #include в качестве инструкции для компилятора, чтобы скопировать/вставить содержимое этого файла в ваш код, чтобы вы получили обработанный файл main.cpp, который выглядит как

#include <iostream> // actually you'll get the contents of the iostream header here, but I'm not going to include it!
int foo(int a){
    return ++a;
}

int main(int argc, char *argv[])
{
int x=42;
std::cout << x <<std::endl;
std::cout << foo(x) << std::endl;
return 0;
}

и foo.cpp

int foo(int a){
    return ++a;
}

следовательно, ошибка множественного определения

Ответ 7

Из-за Одно правило определения (возможно, 1).

В С++ каждый не-встроенный объект и функция должны иметь ровно одно определение внутри программы. В #include файле, в котором определяется foo(int) (файл CPP), он определяется как в каждом файле, где foop.cpp равен #include d, так и в foop.cpp(при условии, что foop.cpp скомпилирован).

Вы можете сделать функцию inline переопределить это поведение, но я не рекомендую это здесь. Я никогда не видел ситуации, когда это необходимо или даже желательно для #include файла CPP.

Бывают ситуации, когда желательно включить определение чего-то. Это особенно актуально, когда вы пытаетесь отделить определение шаблона от его объявления. В этих случаях я называю файл HPP, а не CPP, чтобы обозначить разницу.


1: "(возможно)" Я говорю, вероятно, потому, что фактический код, который вы опубликовали, должен компилироваться без ошибок, но с учетом ошибки компилятора кажется вероятным, что код, который вы опубликовали, точно так же, как и код, который вы компилируете.

Ответ 8

Использование метода ".h" лучше Но если вы действительно хотите включить файл .cpp, тогда сделайте foo (int) static в foo.cpp

Ответ 9

Если кто-то, играющий с шаблонным кодом для экспериментов, хочет включить файлы CPP, это можно сделать, исключив включенный файл CPP из этапа компиляции/сборки. Таким образом, компоновщик будет иметь только одно определение.