Multiple definition of main ошибка code blocks

[Noob programmer] "Multiple definitions of 'main' "

otreblA_SNAKE_[ITA]

Hi there guys,
I’m studying C++ with Deitel «C++ How To Program» and I’ve done a small «gradebook» program. However I’ve a problem: when I try tu build&run my program I’ve an error:

C:UsersAlbertoAppDataLocalTempccSdybij.o:main.cpp|| multiple definition of `main’|
objDebugmain.o:C:UsersAlbertoDocumentsProgetti C++ CodeBlocksConsoleApplication24main.cpp|10|first defined here|
||=== Build finished: 2 errors, 0 warnings ===|

Here’s my simple program:

gradebook.h

#include <string>
using std::string;

class GradeBook
{
    public:
    GradeBook( string );
    void setCourseName( string );
    string getCourseName();
    void displayMessage();

    private:
    string courseName;
};

gradebook.cpp

#include <iostream>
using std::cout;
using std::endl;

#include "GradeBook.h"

GradeBook::GradeBook( string name )
{
    setCourseName( name );
}

void GradeBook::setCourseName( string name )
{
    if ( name.length() <= 25 )
    courseName = name;

    if ( name.length() > 25 )
    {

                courseName = name.substr( 0, 25 );

        cout << "Name "" << name << "" exceeds maximum lenght (25).n" << "Limiting courseName to first 25 characters.n" << endl;

            }

}

string GradeBook::getCourseName()
{
    return courseName;
}

void GradeBook::displayMessage()
{

        cout << "Welcome to the GradeBook forn" << getCourseName() << "!" << endl;
}

Main.cpp

#include <iostream>
using std::cout;
using std::endl;

#include "GradeBook.h"
int main()
{
    //creazione di due oggetti GradeBook
    GradeBook gradeBook1( "CS101 Introduction to C++ Programming" );
    GradeBook gradeBook2( "CS102 Data Structures in C++" );

       cout << "gradeBook1's initial name is: " << gradeBook1.getCourseName() << "ngradeBook2's initial name is: " << gradeBook2.getCourseName() << endl;

        gradeBook1.setCourseName( "CS101 C++ Programming" );

       cout << "ngradeBook1's course name is: " << gradeBook1.getCourseName() << "ngradeBook2's course name is: " << gradeBook2.getCourseName() << endl;
    return 0;
}

In my «Linker Settings» I’ve included both gradebook.h and gradebook.cpp files but that doesn’t help

Thank you,
otreblA

« Last Edit: June 23, 2010, 11:40:07 am by otreblA_SNAKE_[ITA] »


Logged

Я часами застреваю над проблемой, которая, вероятно, очень тривиальна.

Это самое основное использование классов.

Заголовочный файл: person.h

class person
{
protected:
std::string _Name;
public:
void setName(std::string);
};

Реализация: person.cpp

#include <string>
#include "person.h"
void person::setName(std::string name)
{
_Name = name;
}

Драйвер: main.cpp

#include <iostream>
#include "person.cpp"
int main()
{
std::cout << "Yes, it worked.n";
return 0;
}

При попытке скомпилировать этот код в CodeBlocks (используя GNU GCC), я получаю сообщение об ошибке:

~person.cpp|5|multiple definition of `person::setName(std::string)'|
~person.cpp|5|first defined here|
||=== Build finished: 2 errors, 0 warnings (0 minutes, 0 seconds) ===|

У меня есть прототип в заголовочном файле и тело в файле реализации. Где множественное определение? Это работает, если я добавлю «inline» перед «void» в person.cpp, но зачем мне в этом случае?

Кроме того, при компиляции того же точного кода в cmd, что и «g ++ main.cpp -o main.exe», он работает отлично (без встроенного)!

2

Решение

Вам не нужно включать *.cpp файл в main.cpp. Вы должны включить *.h файл.

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

Кроме того, вам нужно добавить включить охрану

#ifndef MY_HEADER
#define MY_HEADER
... code of your header file ...
#endif

или просто добавь

#pragma once

если ваш компилятор поддерживает это.

4

Другие решения

произошло ли это сегодня.

при добавлении файла в кодовые блоки с помощью file — new и т. д. появляется экран, который спрашивает, хотите ли вы включить файл в отладочную и выпускную версии. Вы невинно отвечаете «да», ставя галочки. в результате файл автоматически включается, и когда вы явно включаете его самостоятельно, вы в конечном итоге дублируете. поэтому не ставьте галочки в этих клетках.

ура
толстяк-коротышка

2

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

g ++ main.cpp -o main.o

g ++ person.cpp -o person.o

и затем создайте окончательный выходной файл, используя два .o файла. Поскольку main.cpp включает в себя func.cpp, вы столкнетесь с ошибкой множественного объявления.

Теперь, если вы оставите в проекте только файл main.cpp, только он будет скомпилирован, и вы не получите ту же ошибку.

0

Антон (LogRus)

Глобальный модератор

ru
Offline Offline
Пол: Мужской

Внимание! Люблю сахар в кубиках!

WWW


P.S. Разве так сложно написать (компилятору), что он не знает какой main запустить, потому что их больше одного в проекте… Криворукие программисты  Я зол!

а это что написано?

  multiple definition of `main’ ,   first defined here

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

Вот натолкнулся на проблему: знаю путь к папке, но как проверить, что это именно папка, а не файл?

если линукс, то используем stat
во кусок из BOOST

      status_api( const std::string & ph, error_code & ec )
      {
        struct stat path_stat;
        if ( ::stat( ph.c_str(), &path_stat ) != 0 )
        {
          if ( errno == ENOENT || errno == ENOTDIR )
          {
            ec = ok;
            return fs::file_status( fs::file_not_found );
          }
          ec = error_code( errno, system_category );
          return fs::file_status( fs::status_unknown );
        }
        ec = ok;
        if ( S_ISDIR( path_stat.st_mode ) )
          return fs::file_status( fs::directory_file );
        if ( S_ISREG( path_stat.st_mode ) )
          return fs::file_status( fs::regular_file );
        if ( S_ISBLK( path_stat.st_mode ) )
          return fs::file_status( fs::block_file );
        if ( S_ISCHR( path_stat.st_mode ) )
          return fs::file_status( fs::character_file );
        if ( S_ISFIFO( path_stat.st_mode ) )
          return fs::file_status( fs::fifo_file );
        if ( S_ISSOCK( path_stat.st_mode ) )
          return fs::file_status( fs::socket_file );
        return fs::file_status( fs::type_unknown );
      }

есть такой кусок для винды, но принцип тот же:

  template< class String >
  fs::file_status status_template( const String & ph, error_code & ec )
  {
    DWORD attr( get_file_attributes( ph.c_str() ) );
    if ( attr == 0xFFFFFFFF )
    {
      ec = error_code( ::GetLastError(), system_category );
      if ((ec.value() == ERROR_FILE_NOT_FOUND)
        || (ec.value() == ERROR_PATH_NOT_FOUND)
        || (ec.value() == ERROR_INVALID_NAME) // «tools/jam/src/:sys:stat.h», «//foo»
        || (ec.value() == ERROR_INVALID_PARAMETER) // «:sys:stat.h»
        || (ec.value() == ERROR_BAD_PATHNAME) // «//nosuch» on Win64
        || (ec.value() == ERROR_BAD_NETPATH)) // «//nosuch» on Win32
      {
        ec = ok; // these are not considered errors;
                           // the status is considered not found
        return fs::file_status( fs::file_not_found );
      }
      else if ((ec.value() == ERROR_SHARING_VIOLATION))
      {
        ec = ok; // these are not considered errors;
                           // the file exists but the type is not known
        return fs::file_status( fs::type_unknown );
      }
      return fs::file_status( fs::status_unknown );
    }
    ec = ok;;
    return (attr & FILE_ATTRIBUTE_DIRECTORY)
      ? fs::file_status( fs::directory_file )
      : fs::file_status( fs::regular_file );
  }

Undisputed, ну тогда как разорвать связь красиво?
Допустим я следующим образом видоизменю код:

general.h

C++
1
2
3
4
5
6
7
#ifndef PR1_GENERAL_H
#define PR1_GENERAL_H
 
#include "cl.h"
int sum(cl ob);
 
#endif //PR1_GENERAL_H

general.cpp

C++
1
2
3
4
5
6
#include "general.h"
 
int sum(cl ob)
{
    return ob.x + ob.y;
}

cl.h

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
#ifndef PR1_CL_H
#define PR1_CL_H
 
#include "general.h"
 
class cl {
    int x, y;
public:
    cl() {x = 1; y = 1;}
    friend int sum(cl ob);
};
 
#endif //PR1_CL_H

Тогда в выводе я получаю:

Кликните здесь для просмотра всего текста

====================[ Build | pr1 | Debug ]=====================================
«C:Program FilesJetBrainsCLion 2019.3.3bincmakewinbincmake.exe» —build K:devcpppr1cmake-build-debug —target pr1 — -j 2
Scanning dependencies of target pr1
[ 28%] Building CXX object CMakeFiles/pr1.dir/main.cpp.obj
[ 28%] Building CXX object CMakeFiles/pr1.dir/general.cpp.obj
In file included from K:devcpppr1cl.h:9,
from K:devcpppr1main.cpp:6:
K:devcpppr1general.h:12:9: error: ‘cl’ was not declared in this scope
int sum(cl ob);
^~
In file included from K:devcpppr1main.cpp:6:
K:devcpppr1cl.h:15:25: error: ‘int sum(cl)’ redeclared as different kind of symbol
friend int sum(cl ob);
^
In file included from K:devcpppr1cl.h:9,
from K:devcpppr1main.cpp:6:
K:devcpppr1general.h:12:5: note: previous declaration ‘int sum’
int sum(cl ob);
^~~
mingw32-make.exe[3]: *** [CMakeFilespr1.dirbuild.make:62: CMakeFiles/pr1.dir/main.cpp.obj] Error 1
mingw32-make.exe[3]: *** Waiting for unfinished jobs….
mingw32-make.exe[2]: *** [CMakeFilesMakefile2:75: CMakeFiles/pr1.dir/all] Error 2
mingw32-make.exe[1]: *** [CMakeFilesMakefile2:82: CMakeFiles/pr1.dir/rule] Error 2
mingw32-make.exe: *** [Makefile:117: pr1] Error 2

Не понятно почему «error: ‘cl’ was not declared in this scope» ведь я же указал include’ом заголовочный файл cl.h. Судя по документации Еще на этапе препроцессинга этот кусок с определением класса должен попасть в general.h и значит определение в месте с ним.

Но если я сделаю в файле
general.h

C++
1
2
3
4
5
6
7
#ifndef PR1_GENERAL_H
#define PR1_GENERAL_H
 
class cl;
int sum(cl ob);
 
#endif //PR1_GENERAL_H

и в файле:

general.cpp

C++
1
2
3
4
5
6
7
#include "general.h"
#include "cl.h"
 
int sum(cl ob)
{
    return ob.x + ob.y;
}

, то все работает.

В общем:
1) при компиляции файла general.cpp нужно уже не просто ссылку на имя класса cl, а его определение.
2) при подключении объявлении имен в general.h достаточно знать только лишь ссылки на используемые имена ( определения не обязательно знать )

Но остается недопонимание того, почему при включении в general.h заголовочного файла cl.h происходить ругань:

K:devcpppr1general.h:9:9: error: ‘cl’ was not declared in this scope

Это что выходит, что определение не является объявлением? Мы же туда подставили целое определение…
(см. вложение)

Понравилась статья? Поделить с друзьями:
  • Multiple crashes detected epic games как исправить на русском
  • Multiple comparison error
  • Mse среднеквадратическая ошибка
  • Multiplayer is disabled please check your microsoft account как исправить
  • Multipath error getting device debian