Lnk2005 как исправить

Whiteha, include guard это те самые

C
1
2
3
4
#ifndef FILENAME_H
#define FILENAME_H
 
#endif

Защищают от множественного включения одного файла. Если, например, сделать

C
1
2
#include "something1.h"
#include "something2.h"

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

Директива #include просто подставляет содержимое файла. Так что сами представьте, что будет, если подставить содержимое одного файла дважды. Уж точно ничего хорошего

Цитата
Сообщение от Whiteha
Посмотреть сообщение

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

Совершенно верно. Однако, следует помнить, что иные способы могут вызвать кучу недоразумений и непониманий. Собственно отсюда и пошли традиции — чтобы все друг друга понимали.

Цитата
Сообщение от Kuzia domovenok
Посмотреть сообщение

Скажи, зачем мэйкфайлы человеку пытающемуся создать первый проект из двух файлов спп в MSVS? Инклуд стражи он уже использовал не там где надо.

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

Не по теме:

Цитата
Сообщение от Kuzia domovenok
Посмотреть сообщение

Мне впадлу было.

Я так посмотрю с Вами часто такое.

Background

I have a project named PersonLibrary which has two files.

  1. Person.h
  2. Person.cpp

This library produces a static library file. Another project is TestProject which uses the PersonLibrary (Added though project dependencies in VS008). Everything worked fine until I added a non-member function to Person.h. Person.h looks like

class Person
{
public:
    void SetName(const std::string name);

private:
    std::string personName_;
};

void SetPersonName(Person& person,const std::string name)
{
    person.SetName(name);
}

Person.cpp defines SetName function. When I try to use SetPersonName from TestProject, I get error LNK2005: already defined. Here is how I used it

#include "../PersonLibrary/Person.h"
int main(int argc, char* argv[])
{
    Person person;
    SetPersonName(person, "Bill");
    return 0;
}

Workarounds tried

1 — I have removed the Person.cpp and defined the whole class in Person.h. Error gone and everything worked.

2 — Changed the SetPersonName modifier to static. Like the below

static void SetPersonName(Person& person,const std::string name)
{
    person.SetName(name);
}

Questions

  1. Why the code shown first is not working as I expected?
  2. What difference static made here?
  3. What is the approapriate solution for this problem?

Thanks

asked Mar 7, 2009 at 18:05

Navaneeth K N's user avatar

Navaneeth K NNavaneeth K N

15.2k37 gold badges126 silver badges184 bronze badges

You either have to

  • move SetPersonName‘s definition to a .cpp file, compile and link to the resulting target
  • make SetPersonName inline

This is a well known case of One Definition Rule violation.

The static keyword makes the function’s linkage internal i.e. only available to the translation unit it is included in. This however is hiding the real problem. I’d suggest move the definition of the function to its own implementation file but keep the declaration in the header.

demented hedgehog's user avatar

answered Mar 7, 2009 at 18:11

dirkgently's user avatar

dirkgentlydirkgently

107k16 gold badges131 silver badges187 bronze badges

4

When you compile you’re library, its lib file contains a definition for SetPersonName. When you compile your program that uses the library, since it includes the header, and you’ve written the code inline in the header it also compiles in a definition for SetPersonName. Two definitions for the same function aren’t (generally) allowed. The static keyword tells the compiler that the function shouldn’t be exposed outside of the current translation unit (discrete piece of code you are compiling), so the definition in the library isn’t visible to the linker.

The appropriate solution to this problem depends on your goals. Header files with static function declarations is almost never what you want. From a design standpoint I would recommend getting rid of SetPersonName altogether, and just use Person::SetName.

However, failing that, I would implement it much like you’ve done for the rest of your functionality, declarations in the header, and implementation in the .cpp. Inline functions associated with a library will tend to diminish many of the advantages of using a library in the first place.

answered Mar 7, 2009 at 18:22

Logan Capaldo's user avatar

Logan CapaldoLogan Capaldo

39.4k5 gold badges63 silver badges78 bronze badges

By declaring the function static you are scoping it to the current translation unit, so in effect you have added a new SetPersonName function in your main file, and would be calling that not the one defined in the library.

The correct solution is to declare SetPersonName as extern in person.h and implement it in person.cpp

Person.h

extern void SetPersonName(Person& person,const std::string name);

Person.cpp

void SetPersonName(Person& person,const std::string name)
{
    person.SetName(name);
}

answered Mar 7, 2009 at 18:12

Rob Walker's user avatar

Rob WalkerRob Walker

46.4k15 gold badges98 silver badges136 bronze badges

  1. The function SetPersonName will be compiled into each objectfile that includes the Person.h file, thus making the linker seeing several functions and giving the error.

  2. By writing static you state that the function will only be visible within a single objectfile. You will still get several functions in you binary but now you will not get the errors.

  3. Try to write inline before the function like

    inline void SetPersonName(Person& person,const std::string name)
    {
        person.SetName(name);
    }
    

    …because the function is pretty simple it is OK I think to have it as an inline. An inline will place the necessary code where the function is used, without actually creating a function to be called.

answered Mar 7, 2009 at 18:09

epatel's user avatar

A solution would be to make that function a static method. That will stop the «already defined» errors.

answered Mar 7, 2009 at 18:18

Geo's user avatar

GeoGeo

92.8k117 gold badges342 silver badges518 bronze badges

I had a similar situation as described clearly by @logan-capaldo above.

A CPP source file (myfile.cpp) contained a function MyFunction. When building, this got compiled into myfile.obj. But the main CPP file (main.cpp) also included myfile.cpp, so the function MyFunction was being included/compiled/linked twice, leading to the «LNK2005 already defined» error.

This is messy but I didn’t have time to fix it properly. The quickest fix (in VS Express 2012) was to right-click myfile.cpp in Solution Explorer, go to Properties and change Excluded From Build to Yes. I guess this prevents one of the OBJ files from being created and/or linked and so removes the error.

answered Jan 27, 2016 at 16:22

Paul's user avatar

PaulPaul

6598 silver badges9 bronze badges

For anyone landing here dealing with this error in a Qt project, make sure you don’t have any non-signal functions defined under signals: in your header files.

Incorrect, throws LNK2005 on Foo::promiseData():

class Foo : public QObject {
        Q_OBJECT

    public:
        explicit Foo(QObject* parent = nullptr);

    signals:
        void dataReady(QList<QObject*> data) const;

        void promiseData() const; // <-- This function is not supposed to be a signal.

Correct:

class Foo : public QObject {
        Q_OBJECT

    public:
        explicit Foo(QObject* parent = nullptr);

        void promiseData() const;

    signals:
        void dataReady(QList<QObject*> data) const;

answered Sep 13, 2019 at 21:18

Clifton Roberts's user avatar

If you want both to reference the same variable, one of them should have int k;, and the other should have extern int k;

For this situation, you typically put the definition (int k;) in one .cpp file, and put the declaration (extern int k;) in a header, to be included wherever you need access to that variable.

If you want each k to be a separate variable that just happen to have the same name, you can either mark them as static, like: static int k; (in all files, or at least all but one file). Alternatively, you can us an anonymous namespace:

namespace { 
   int k;
};

Again, in all but at most one of the files.

In C, the compiler generally isn’t quite so picky about this. Specifically, C has a concept of a «tentative definition», so if you have something like int k; twice (in either the same or separate source files) each will be treated as a tentative definition, and there won’t be a conflict between them. This can be a bit confusing, however, because you still can’t have two definitions that both include initializers—a definition with an initializer is always a full definition, not a tentative definition. In other words, int k = 1; appearing twice would be an error, but int k; in one place and int k = 1; in another would not. In this case, the int k; would be treated as a tentative definition and the int k = 1; as a definition (and both refer to the same variable).

Привет!
Возникла проблема в VS 2017 с ошибкой линкования файлов (LNK2005), прикреплю скриншоты для наглядности.
В проекте 3 файла:

  • MyForm.h — файл самой формы C++CLI, здесь я делаю #include «source.cpp», что скорее всего и падает, также здесь использую методы взаимодействия с формой типа openFileDialog и т.д.

    spoiler

    5ae43dbb2f7b7003435962.jpeg5ae43dc33f59b774396348.jpeg

  • Source.cpp — основной скрипт на 1.3к строк, мне нужно в MyForm.h вызвать вызвать функцию void solve() {…}, которая работает только в пределах стандартных библиотек и самого Source.cpp, не вызывая ничего «изнутри», для простоты все закомментировал и во всем файле оставил:
    void solve() {
    //
    }

    spoiler

    5ae43ddd48cb6764306187.jpeg

  • MyForm.cpp — нужен только для определения точки входа в приложение, там ничего не происходит.

    spoiler

    5ae43e12a57d5011363197.jpeg

Возможно напутал с пространством имен или подключением, но если создать заголовок H1.h, где написать:

#include "source.cpp"
void solve();

— тоже не рабит(
В гугле нашел информацию про переопределение в нескольких файлах одной и той же функции, но у меня всего 1 файл с определением и подключаю его всего 1 раз;
Если мысль, что ошибка из-за того, что подключаю как-то так: Source.cpp -> MyForm.h -> MyForm.cpp…
Подскажите, как правильно!

    msm.ru

    Нравится ресурс?

    Помоги проекту!

    !
    Правила раздела Visual C++ / MFC / WTL (далее Раздела)

    >
    error LNK2005, исправление.
    , Якобы уже определен класс

    • Подписаться на тему
    • Сообщить другу
    • Скачать/распечатать тему



    Сообщ.
    #1

    ,
    21.06.08, 13:38

      В Visual C++ 6 необходимо разбить программу на ООП на файлы, так, чтобы один файл (*.h) содержал сам класс, аналогичный *.cpp файл содержал функции этого класса.
      Когда всё в одном файле, то всё работает, при разбиении на файлы (для начала я выношу один класс, остальный пока не трогаю), то возникают ошибки:

      ExpandedWrap disabled

        Kursach.obj : error LNK2005: «public: __thiscall Chelovek::Chelovek(char *,char *,char *)» (??0Chelovek@@QAE@PAD00@Z) already defined in Chelovek.obj

        Kursach.obj : error LNK2005: «public: __thiscall Chelovek::Chelovek(char *)» (??0Chelovek@@QAE@PAD@Z) already defined in Chelovek.obj

        Kursach.obj : error LNK2005: «public: __thiscall Chelovek::Chelovek(void)» (??0Chelovek@@QAE@XZ) already defined in Chelovek.obj

      При это, есть файл Chelovek.h с таким содержанием:

      ExpandedWrap disabled

        #ifndef CHELOVEK_H

        #define CHELOVEK_H

        #include <fstream.h>

        class Chelovek

        {

        protected:

            char Name[15];

            char Family[15];

            char Otchestvo[15];

        public:

            int ID;

            Chelovek(char *Nm,char *Fm,char *Ot);

            Chelovek(char *Fm);

            Chelovek();

            ~Chelovek(){};

            virtual void print()= 0;// Чистая виртуальная функция

            virtual int fwrite()= 0;

            virtual int Fwrite(fstream f)= 0;// Чистая виртуальная функция

            virtual int fread()=0;// Чистая виртуальная функция

            virtual int Fread(ifstream f)= 0;

        };

        #endif

      А файл Chelovek.cpp имеет такое содержание:

      ExpandedWrap disabled

        #include «Chelovek.h»

        #include <string.h>

        Chelovek::Chelovek(char *Nm,char *Fm,char *Ot)

        {

            ID=0;

            strcpy(Name,Nm);

            strcpy(Family,Fm);

            strcpy(Otchestvo,Ot);

        }

        Chelovek::Chelovek(char *Fm)

        {

            ID=0;

            strcpy(Family,Fm);

        }

        Chelovek::Chelovek()

        {

            char *y;

            y=»»;

            ID=0;

            strcpy(Name,y);

            strcpy(Family,y);

            strcpy(Otchestvo,y);

        }

      А в основном файле просто инклудится Chelovek.cpp.
      Насколько, как мне кажется, проблема скорее всего в h файле, и, насколько я знаю, за это отвечают первые две строки…
      Но не понимаю почему такая проблема возникает(((
      Подскажите пожалуйста, что именно нужно добавить или убрать, чтобы не возникало такой ошибки.
      Мне кажется что проблема не очень сложная (я даже ни на этом, ни на нескольких других форумах) не нашёл ответа на этот вопрос, но не очень хорошо разбираюсь в С++.

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

      Сообщение отредактировано: антиКИЛЛЕР — 21.06.08, 13:39


      Juni



      Сообщ.
      #2

      ,
      21.06.08, 13:52

        // h
        #include <fstream>

        class Chelovek
        {
        private:
        char Name[15];
        char Family[15];
        char Otchestvo[15];
        public:
        int ID;
        Chelovek(char *Nm,char *Fm,char *Ot);
        Chelovek(char *Fm);
        Chelovek();
        ~Chelovek(){};
        virtual void print()= 0;// Чистая виртуальная функция
        virtual int fwrite()= 0;
        virtual int Fwrite(std::fstream f)= 0;// Чистая виртуальная функция
        virtual int fread()=0;// Чистая виртуальная функция
        virtual int Fread(std::ifstream f)= 0;
        };

        //cpp
        #include «Chelovek.h»
        #include <string.h>
        Chelovek::Chelovek(char *Nm,char *Fm,char *Ot)
        {
        ID=0;
        strcpy(Name,Nm);
        strcpy(Family,Fm);
        strcpy(Otchestvo,Ot);
        }

        Chelovek::Chelovek(char *Fm)
        {
        ID=0;
        strcpy(Family,Fm);
        }

        Chelovek::Chelovek()
        {
        char *y;
        y=»»;
        ID=0;
        strcpy(Name,y);
        strcpy(Family,y);
        strcpy(Otchestvo,y);
        }

        попробуй

        Сообщение отредактировано: Juni — 21.06.08, 13:54


        антиКИЛЛЕР



        Сообщ.
        #3

        ,
        21.06.08, 14:14

          Juni,
          Так к сожалению, тоже не работает.
          Выскакивает всего 58 ошибок, начинающихся с таких:

          ExpandedWrap disabled

            f:институткурсовая тех прогkursachchelovek.h(17) : error C2653: ‘std’ : is not a class or namespace name

            f:институткурсовая тех прогkursachchelovek.h(19) : error C2653: ‘std’ : is not a class or namespace name

            F:ИНСТИТУТКурсовая Тех прогKursachKursach.cpp(173) : error C2248: ‘Name’ : cannot access private member declared in class ‘Chelovek’

                    f:институткурсовая тех прогkursachchelovek.h(6) : see declaration of ‘Name’

          Далее список ошибок приводить не буду, т.к. они относятся к тому, что программа не может получить доступ к данным private.

          В случае, если просто убрать такие строки:

          ExpandedWrap disabled

            #ifndef CHELOVEK_H

            #define CHELOVEK_H

            #endif

          то возникает ошибка открытия файла Chelovek.obj:

          ExpandedWrap disabled

            LINK : fatal error LNK1104: cannot open file «.DebugChelovek.obj»

            Error executing link.exe.


          антиКИЛЛЕР



          Сообщ.
          #4

          ,
          21.06.08, 15:15

            По ходу компилятор переглючил. Сейчас запустил и теперь уже находится Chelovek.obj и возникают те же самые ошибки error LNK2005.


            Hryak



            Сообщ.
            #5

            ,
            21.06.08, 16:15

              Цитата антиКИЛЛЕР @ 21.06.08, 13:38

              А в основном файле просто инклудится Chelovek.cpp.
              Насколько, как мне кажется, проблема скорее всего в h файле,

              Проблема в том, что ты инклудишь .cpp-файл. Так не делается.
              Добавляй .cpp в проект и всё, инклудь где нужно только .h-файл


              антиКИЛЛЕР



              Сообщ.
              #6

              ,
              21.06.08, 19:34

                Hryak,
                Браво! Да действительно, проблема была именно в этом!!

                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)

                0 пользователей:

                • Предыдущая тема
                • Visual C++ / MFC / WTL
                • Следующая тема

                Рейтинг@Mail.ru

                [ Script execution time: 0,0310 ]   [ 16 queries used ]   [ Generated: 29.05.23, 10:34 GMT ]  

                Понравилась статья? Поделить с друзьями:
              • Собака погрызла мебель как исправить
              • Genshin impact как найти последнюю геокулу
              • Овен как найти работу
              • Как найти процент от числа формула калькулятор
              • Как найти знахарку самарской области