Проблема множественного определения в netbeans - PullRequest
0 голосов
/ 04 сентября 2011

У меня есть 2 файла, а именно fun.cpp и main.cpp

fun.cpp

#include <iostream>
using namespace std;

void sum()
{
    cout << "hello";
}

Main.cpp

#include <cstdlib>
#include <iostream>
#include "fun.cpp"
using namespace std;

int main(int argc, char** argv) {

sum();

    return 0;
}

Когда я запускаю приведенный выше код в netbeans, я получаю такой вывод

"/usr/bin/make" -f nbproject/Makefile-Debug.mk QMAKE= SUBPROJECTS= .build-conf
make[1]: Entering directory `/home/ravi/NetBeansProjects/ADBMS_v1.5'
"/usr/bin/make"  -f nbproject/Makefile-Debug.mk dist/Debug/GNU-Linux-x86/adbms_v1.5
make[2]: Entering directory `/home/ravi/NetBeansProjects/ADBMS_v1.5'
mkdir -p dist/Debug/GNU-Linux-x86
g++     -o dist/Debug/GNU-Linux-x86/adbms_v1.5 build/Debug/GNU-Linux-x86/fun.o build/Debug/GNU-Linux-x86/main.o  
build/Debug/GNU-Linux-x86/main.o: In function `sum()':
/home/ravi/NetBeansProjects/ADBMS_v1.5/fun.cpp:5: multiple definition of `sum()'
build/Debug/GNU-Linux-x86/fun.o:/home/ravi/NetBeansProjects/ADBMS_v1.5/fun.cpp:5: first defined here
collect2: ld returned 1 exit status
make[2]: *** [dist/Debug/GNU-Linux-x86/adbms_v1.5] Error 1
make[1]: *** [.build-conf] Error 2
make: *** [.build-impl] Error 2
make[2]: Leaving directory `/home/ravi/NetBeansProjects/ADBMS_v1.5'
make[1]: Leaving directory `/home/ravi/NetBeansProjects/ADBMS_v1.5'

BUILD FAILED (exit value 2, total time: 150ms)

Может кто-нибудь объяснить, в чем проблема ??

Заранее спасибо ..

Ответы [ 2 ]

3 голосов
/ 04 сентября 2011

Не включать файл cpp, который имеет определение функции в других файлах cpp.
Это вызывает множество определений функций для одних и тех же функций и нарушает правило One Definition .

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

fun.h

#ifndef HEADER_FUN_H
#define HEADER_FUN_H

void sum();

#endif //HEADER_FUN_H

fun.cpp

#include "fun.h"
#include <iostream>
using namespace std;

void sum()
{
    cout << "hello";
}

main.cpp

#include <cstdlib>
#include <iostream>
#include "fun.h"
using namespace std;

int main(int argc, char** argv) 
{
    sum();
    return 0;
}
1 голос
/ 04 сентября 2011

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

Прежде чем компилятор фактически скомпилирует код, он сначала выполняет все операторы предварительной обработки, например, операторы #include в обоих ваших .cpp файлах. Оператор #include просто берет содержимое указанного файла и «копирует» его в файл, где находится оператор #include. Например, fun.cpp может выглядеть следующим образом после предварительной обработки:

/* the contents of the iostream file goes here */
using namespace std; 
void sum() 
{ 
    cout << "hello"; 
} 

Для Main.cpp, что-то вроде этого:

/* the contents of the cstdlib file goes here */
/* the contents of the iostream file goes here */
using namespace std; 
void sum() 
{ 
    cout << "hello"; 
} 
int main(int argc, char** argv)
{  
    sum();  
    return 0;  
}  

Как видите, содержимое fun.cpp было "вставлено" в Main.cpp. Итак, теперь у вас есть два определения sum(), что является нарушением правила единого определения (ODR) в C ++. Поскольку компилятор обрабатывает каждую единицу перевода отдельно, эта ошибка не была обнаружена, пока компоновщик не обнаружил, что у вас есть два разных определения, и в результате справедливо пожаловался.

Поскольку функция sum() довольно проста, один из способов решения этой проблемы - сделать функцию sum() inline, переименовать файл fun.cpp в fun.h и включить fun.h в * 1030. * вместо fun.cpp.

// fun.h
#include <iostream>
inline void sum()
{
    std::cout << "hello";
}

// main.cpp
#include <cstdlib>         
#include <iostream>         
#include "fun.h" // Note "fun.h" 

int main(int argc, char** argv)
{         
    sum();
    return 0;
}

Для больших функций или если вы хотите скрыть реализацию, ответ Als более уместен.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...