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

Your privacy

By clicking “Accept all cookies”, you agree Stack Exchange can store cookies on your device and disclose information in accordance with our Cookie Policy.

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

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

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

07-04-2013


#1

amber18 is offline


Registered User



07-05-2013


#8

stahta01 is offline


Registered User


Quote Originally Posted by Elysia
View Post

One project = one program.
One program consists of many source files that are merged together into one file (executable). A project is a way to keep all these files together and merge them into a single file.
So, to create a new program, create a new project. That’s all.

Technically you could just create a separate CB target for each main function.

Tim S.

«…a computer is a stupid machine with the ability to do incredibly smart things, while computer programmers are smart people with the ability to do incredibly stupid things. They are,in short, a perfect match..» Bill Bryson


Антон (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 );
  }

Перейти к контенту

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

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

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

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

Заголовочный файл: 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

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

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

Заголовок файла: 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», он отлично работает (без встроенного)!

I found something that at least begins to answer my own question. The following two links have wmv files from Microsoft that demonstrate using a C# class in unmanaged C++.

This first one uses a COM object and regasm: http://msdn.microsoft.com/en-us/vstudio/bb892741.

This second one uses the features of C++/CLI to wrap the C# class: http://msdn.microsoft.com/en-us/vstudio/bb892742. I have been able to instantiate a c# class from managed code and retrieve a string as in the video. It has been very helpful but it only answers 2/3rds of my question as I want to instantiate a class with a string perimeter into a c# class. As a proof of concept I altered the code presented in the example for the following method, and achieved this goal. Of course I also added a altered the {public string PickDate(string Name)} method to do something with the name string to prove to myself that it worked.

wchar_t * DatePickerClient::pick(std::wstring nme)
{
    IntPtr temp(ref);// system int pointer from a native int
    String ^date;// tracking handle to a string (managed)
    String ^name;// tracking handle to a string (managed)
    name = gcnew String(nme.c_str());
    wchar_t *ret;// pointer to a c++ string
    GCHandle gch;// garbage collector handle
    DatePicker::DatePicker ^obj;// reference the c# object with tracking handle(^)
    gch = static_cast<GCHandle>(temp);// converted from the int pointer 
    obj = static_cast<DatePicker::DatePicker ^>(gch.Target);
    date = obj->PickDate(name);
    ret = new wchar_t[date->Length +1];
    interior_ptr<const wchar_t> p1 = PtrToStringChars(date);// clr pointer that acts like pointer
    pin_ptr<const wchar_t> p2 = p1;// pin the pointer to a location as clr pointers move around in memory but c++ does not know about that.
    wcscpy_s(ret, date->Length +1, p2);
    return ret;
}

Part of my question was: What is better? From what I have read in many many efforts to research the answer is that COM objects are considered easier to use, and using a wrapper instead allows for greater control. In some cases using a wrapper can (but not always) reduce the size of the thunk, as COM objects automatically have a standard size footprint and wrappers are only as big as they need to be.

The thunk (as I have used above) refers to the space time and resources used in between C# and C++ in the case of the COM object, and in between C++/CLI and native C++ in the case of coding-using a C++/CLI Wrapper. So another part of my answer should include a warning that crossing the thunk boundary more than absolutely necessary is bad practice, accessing the thunk boundary inside a loop is not recommended, and that it is possible to set up a wrapper incorrectly so that it double thunks (crosses the boundary twice where only one thunk is called for) without the code seeming to be incorrect to a novice like me.

Two notes about the wmv’s. First: some footage is reused in both, don’t be fooled. At first they seem the same but they do cover different topics. Second, there are some bonus features such as marshalling that are now a part of the CLI that are not covered in the wmv’s.

Edit:

Note there is a consequence for your installs, your c++ wrapper will not be found by the CLR. You will have to either confirm that the c++ application installs in any/every directory that uses it, or add the library (which will then need to be strongly named) to the GAC at install time. This also means that with either case in development environments you will likely have to copy the library to each directory where applications call it.

Понравилась статья? Поделить с друзьями:
  • Multifunktionslenkrad ueberwachung schnittstelle ошибка
  • Msz ge22va коды ошибок
  • Multicauseexception invalid file structure электронный бюджет ошибка
  • Msz gc25va коды ошибок
  • Multi usb key ошибка 28