LNK1169 ditemukan satu atau lebih simbol yang ditentukan perkalian Dan LNK2005

Saya mengalami masalah ini ketika saya mencoba mengkompilasi kode saya, saya pikir itu mungkin disebabkan oleh file header yang menyertakan satu sama lain. Namun sejauh yang saya tahu, saya tidak menemukan masalah apa pun dengan file header saya

Kesalahan LNK1169 satu atau lebih simbol yang ditentukan perkalian ditemukan Pekerjaan Rumah2 D:\05Pengembangan\04 C_C++\C\DS Alg class\Homework2\Debug\Homework2.exe 1

juga, ada kesalahan yang memberi tahu saya bahwa fungsi Assert() telah dideklarasikan di tempat lain.

Kesalahan LNK2005 "void __cdecl Assert(bool,class std::basic_string,class std::allocator >)" (?Assert@@YAX_NV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@ 2@@std@@@Z) sudah ditentukan di DataBase.obj Homework2 D:\05Development\04 C_C++\C\DS Alg class\Homework2\Homework2\dbTest.obj 1

inilah struktur kode saya:

fungsi

void Assert(bool val, string s)
{
    if (!val)
    {
        cout << "Assertion Failed!!: " << s << endl;
        exit(-1);
    }
}

ada di Constants.h

Daftar kelas virtual mencakup Constants.h

#pragma once // List.h
#include "Constants.h"

Daftar array menyertakan kelas Daftar, di kelas AList memanggil fungsi Assert

#pragma once //AList.h
#include "List.h"
...
Assert((pos >= 0) && (pos < listSize), "Position out of range");

Di kelas DataBase saya membuat anggota AList

private:
    AList<CData> set;

headernya terlihat seperti ini: #pragma sekali #include "AList.h" #include "CData.h"

dan CData.h terlihat seperti ini:

#pragma once
class CData
{
private:
    std::string m_name;

    int m_x;
    int m_y;

public:
    CData(std::string str = "null", int x = 0, int y = 0) : m_name(str), m_x(x), m_y(y) {}

    // Helper functions
    const std::string& GetName() const { return this->m_name; }
    const int& GetX() const { return this->m_x; }
    const int& GetY() const { return this->m_y; }
};

person Charlie Lee    schedule 15.10.2018    source sumber
comment
Jangan menaruh kode di file header, kecuali kode inline dalam definisi kelas atau kode templat. Hanya di file .cpp. Di sini implementasi fungsi Assert tidak boleh ada di Constants.h, hanya deklarasinya saja yang harus ada (void Assert(bool val, string s);)   -  person Jabberwocky    schedule 15.10.2018


Jawaban (1)


Saat Anda membangun proyek, setiap file .cpp dikompilasi secara terpisah ke dalam file objek yang berbeda. Tanda once di #pragma once hanya berlaku untuk kompilasi satu file .cpp, bukan untuk proyek secara keseluruhan. Jadi jika file .cpp menyertakan header A dan header B, dan header B juga menyertakan header A, maka penyertaan header A yang kedua akan dilewati.

Namun, jika Anda memiliki file .cpp lain yang menyertakan A, A akan disertakan lagi dalam file objek tersebut -- karena #pragma once hanya berfungsi saat mengkompilasi satu file .cpp.

Pernyataan #include secara harfiah mengambil konten file yang disertakan dan "menempelkannya" ke dalam file yang menyertakannya. Anda dapat mencobanya dengan melihat keluaran alat praprosesor C (cpp di rantai alat gcc). Jika Anda menggunakan toolchain gcc, Anda dapat mencoba sesuatu seperti ini untuk melihat file setelah penyertaannya diterapkan:

cpp file.cpp -o file_with_includes.cpp

Jika Anda memiliki fungsi di header Anda, seperti Assert dalam contoh Anda, fungsi tersebut akan direplikasi ke setiap file .cpp tempat Anda memasukkannya.

Jika Anda memiliki A.cpp dan B.cpp, yang keduanya menyertakan file Constants.h, setiap file objek (.o atau .obj bergantung pada lingkungan Anda) akan menyertakan salinan fungsi Assert Anda. Ketika linker menggabungkan file objek untuk membuat biner, kedua file objek akan menyatakan bahwa mereka memberikan definisi untuk Assert, dan linker akan mengeluh, karena tidak tahu mana yang akan digunakan.

Solusinya di sini adalah dengan menyejajarkan fungsi Assert Anda, seperti ini:

inline void Assert(bool val, string s)
{
    if (!val)
    {
        cout << "Assertion Failed!!: " << s << endl;
        exit(-1);
    }
}

atau untuk menyediakan isi file .cpp-nya sendiri, sehingga hanya menyisakan prototipe fungsi di header.

Konstanta.h:

void Assert(bool val, string s);

Konstanta.cpp:

void Assert(bool val, string s)
{
    if (!val)
    {
        cout << "Assertion Failed!!: " << s << endl;
        exit(-1);
    }
}

Ingat, Perpustakaan Standar juga menawarkan assert(), yang juga berfungsi dengan baik. (lihat https://en.cppreference.com/w/cpp/error/assert).

#include <cassert>
...
assert(is_my_condition_true());
assert(my_variable > 23);
// etc..

Perlu diingat bahwa pernyataan yang dideklarasikan di cassert hanya berfungsi saat kompilasi untuk Debug, dan dikompilasi saat dibuat untuk Rilis (untuk mempercepat eksekusi), jadi jangan memasukkan kode apa pun ke dalam pernyataan yang memiliki efek samping.

#include <cassert>
...
// Don't call functions with side effects.
// Thus function decreases a "count" and returns the new value
// In Release builds, this line will disappear and the decrement
// won't occur.
assert(myclass.decrement_count() > 0);
person BareMetalCoder    schedule 15.10.2018
comment
Saya menyarankan agar Anda secara eksplisit menunjukkan cara inline itu. - person Evg; 15.10.2018
comment
@CharlieLee ini memecahkan masalah Anda =› Anda harus menerima jawabannya - person Jabberwocky; 15.10.2018