Saat membuat program C ++ saya, saya menerima pesan kesalahan
referensi tidak terdefinisi ke 'vtable ...
Apa penyebab masalah ini? Bagaimana saya memperbaikinya?
Kebetulan saya mendapatkan kesalahan untuk kode berikut (Kelas yang dimaksud adalah CGameModule.) Dan saya tidak bisa seumur hidup saya mengerti apa masalahnya. Pada awalnya, saya pikir itu terkait dengan lupa untuk memberikan fungsi virtual pada tubuh, tetapi sejauh yang saya mengerti, semuanya ada di sini. Rantai pewarisan agak panjang, tetapi di sini adalah kode sumber terkait. Saya tidak yakin informasi apa yang harus saya berikan.
Catatan: Konstruktor adalah tempat kesalahan ini terjadi, sepertinya.
Kode saya:
class CGameModule : public CDasherModule {
public:
CGameModule(Dasher::CEventHandler *pEventHandler, CSettingsStore *pSettingsStore, CDasherInterfaceBase *pInterface, ModuleID_t iID, const char *szName)
: CDasherModule(pEventHandler, pSettingsStore, iID, 0, szName)
{
g_pLogger->Log("Inside game module constructor");
m_pInterface = pInterface;
}
virtual ~CGameModule() {};
std::string GetTypedTarget();
std::string GetUntypedTarget();
bool DecorateView(CDasherView *pView) {
//g_pLogger->Log("Decorating the view");
return false;
}
void SetDasherModel(CDasherModel *pModel) { m_pModel = pModel; }
virtual void HandleEvent(Dasher::CEvent *pEvent);
private:
CDasherNode *pLastTypedNode;
CDasherNode *pNextTargetNode;
std::string m_sTargetString;
size_t m_stCurrentStringPos;
CDasherModel *m_pModel;
CDasherInterfaceBase *m_pInterface;
};
Warisan dari ...
class CDasherModule;
typedef std::vector<CDasherModule*>::size_type ModuleID_t;
/// \ingroup Core
/// @{
class CDasherModule : public Dasher::CDasherComponent {
public:
CDasherModule(Dasher::CEventHandler * pEventHandler, CSettingsStore * pSettingsStore, ModuleID_t iID, int iType, const char *szName);
virtual ModuleID_t GetID();
virtual void SetID(ModuleID_t);
virtual int GetType();
virtual const char *GetName();
virtual bool GetSettings(SModuleSettings **pSettings, int *iCount) {
return false;
};
private:
ModuleID_t m_iID;
int m_iType;
const char *m_szName;
};
Yang mewarisi dari ....
namespace Dasher {
class CEvent;
class CEventHandler;
class CDasherComponent;
};
/// \ingroup Core
/// @{
class Dasher::CDasherComponent {
public:
CDasherComponent(Dasher::CEventHandler* pEventHandler, CSettingsStore* pSettingsStore);
virtual ~CDasherComponent();
void InsertEvent(Dasher::CEvent * pEvent);
virtual void HandleEvent(Dasher::CEvent * pEvent) {};
bool GetBoolParameter(int iParameter) const;
void SetBoolParameter(int iParameter, bool bValue) const;
long GetLongParameter(int iParameter) const;
void SetLongParameter(int iParameter, long lValue) const;
std::string GetStringParameter(int iParameter) const;
void SetStringParameter(int iParameter, const std::string & sValue) const;
ParameterType GetParameterType(int iParameter) const;
std::string GetParameterName(int iParameter) const;
protected:
Dasher::CEventHandler *m_pEventHandler;
CSettingsStore *m_pSettingsStore;
};
/// @}
#endif
qmake -project
Dan kemudianqmake
) untuk menghasilkan yang baruMakefile
, itu kemungkinan merupakan sumber kesalahan ketika menggunakan Qt.Q_OBJECT
disalin secara eksternal, tetapi belum menjadi bagian dari file .pro, maka meskipun dikompilasi dengan baik, ia tidak terhubung. Kita harus menambahkan.h/.cpp
file itu ke file .pro untuk dapatqmake
.Jawaban:
The GCC FAQ memiliki entri di atasnya:
sumber
nm -C CGameModule.o | grep CGameModule::
akan mencantumkan metode yang didefinisikan, dengan asumsi seluruh implementasi kelas Anda masuk ke file objek logis. Anda dapat membandingkannya dengan apa yang didefinisikan sebagai virtual untuk mengetahui apa yang Anda lewatkan.Untuk apa nilainya, melupakan tubuh pada destruktor virtual menghasilkan yang berikut:
Saya menambahkan catatan karena pesan kesalahannya menipu. (Ini dengan versi gcc 4.6.3.)
sumber
~Destructor = default;
dalam file header tidak membantu. Apakah ada bug yang didokumentasikan yang diajukan terhadap gcc?Jadi, saya sudah menemukan masalah dan itu adalah kombinasi dari logika yang buruk dan tidak sepenuhnya akrab dengan dunia automake / autotools. Saya menambahkan file yang benar ke template Makefile.am saya, tetapi saya tidak yakin langkah mana dalam proses build kami yang benar-benar membuat makefile itu sendiri. Jadi, saya kompilasi dengan makefile lama yang tidak tahu sama sekali tentang file baru saya.
Terima kasih atas tanggapan dan tautan ke FAQ GCC. Saya pasti akan membaca bahwa untuk menghindari masalah ini terjadi karena alasan yang sebenarnya.
sumber
Jika Anda menggunakan Qt, coba jalankan ulang qmake. Jika kesalahan ini ada di kelas widget, qmake mungkin gagal memperhatikan bahwa kelas ui vtable harus dibuat ulang. Ini memperbaiki masalah bagi saya.
sumber
qmake
, saya memiliki hal yang samacmake
. Bagian dari masalah mungkin adalah bahwa kedua alat memiliki sedikit masalah dengan file header, yang mungkin tidak selalu memicu pembangunan kembali ketika diperlukan.Referensi yang tidak terdefinisi ke vtable dapat terjadi karena situasi berikut juga. Coba saja ini:
Kelas A Berisi:
Kelas B Berisi:
Kelas C Berisi: Sekarang Anda sedang menulis Kelas C di mana Anda akan mendapatkannya dari Kelas A.
Sekarang jika Anda mencoba mengkompilasi Anda akan mendapatkan referensi Undefined ke vtable untuk Kelas C sebagai kesalahan.
Alasan:
functionA
didefinisikan sebagai virtual murni dan definisinya disediakan di Kelas B.functionB
didefinisikan sebagai virtual (BUKAN MURNI VIRTUAL) sehingga mencoba untuk menemukan definisi di Kelas A itu sendiri tetapi Anda memberikan definisi di Kelas B.Larutan:
virtual void functionB(parameters) =0;
(Ini berfungsi, ini Diuji)sumber
Saya hanya mendapatkan kesalahan ini karena file cpp saya tidak ada di makefile.
sumber
undefined reference to {function/class/struct}
ketika adavirtual
hal - hal yang terlibat. Membuang saya.Apa itu
vtable
?Mungkin berguna untuk mengetahui apa yang dibicarakan pesan kesalahan sebelum mencoba memperbaikinya. Saya akan mulai pada tingkat tinggi, kemudian bekerja ke beberapa detail lebih lanjut. Dengan begitu orang dapat langsung beralih begitu mereka merasa nyaman dengan pemahaman mereka tentang tabel. ... dan ada banyak orang yang melompati sekarang :) Bagi mereka yang tinggal di sekitar:
Sebuah vtable pada dasarnya adalah implementasi paling umum dari polimorfisme di C ++ . Ketika vtables digunakan, setiap kelas polimorfik memiliki vtable di suatu tempat dalam program; Anda dapat menganggapnya sebagai anggota
static
data (tersembunyi) dari kelas. Setiap objek dari kelas polimorfik dikaitkan dengan vtable untuk kelas yang paling diturunkan. Dengan memeriksa asosiasi ini, program dapat mengerjakan keajaiban polimorfiknya. Peringatan penting: vtable adalah detail implementasi. Ini tidak diamanatkan oleh standar C ++, meskipun kebanyakan kompiler C ++ (semua?) Menggunakan vtables untuk mengimplementasikan perilaku polimorfik. Rincian yang saya sajikan adalah pendekatan yang khas atau masuk akal. Kompiler diizinkan untuk menyimpang dari ini!Setiap objek polimorfik memiliki pointer (tersembunyi) ke vtable untuk kelas objek yang paling diturunkan (mungkin beberapa pointer, dalam kasus yang lebih kompleks). Dengan melihat pointer, program dapat mengetahui jenis objek "asli" (kecuali selama konstruksi, tetapi mari kita lewati case khusus itu). Sebagai contoh, jika suatu objek bertipe
A
tidak menunjuk ke tabelA
, maka objek tersebut sebenarnya merupakan sub-objek dari sesuatu yang berasalA
.Nama "vtable" berasal dari " v irtual function table ". Ini adalah tabel yang menyimpan pointer ke fungsi (virtual). Compiler memilih konvensi untuk bagaimana tabel ditata; pendekatan sederhana adalah melalui fungsi virtual dalam urutan yang dinyatakan dalam definisi kelas. Ketika fungsi virtual dipanggil, program mengikuti pointer objek ke vtable, pergi ke entri yang terkait dengan fungsi yang diinginkan, kemudian menggunakan pointer fungsi tersimpan untuk menjalankan fungsi yang benar. Ada berbagai trik untuk membuat ini berhasil, tetapi saya tidak akan membahasnya di sini.
Di mana / kapan
vtable
dihasilkan?Sebuah vtable dihasilkan secara otomatis (kadang-kadang disebut "dipancarkan") oleh kompiler. Kompiler dapat memancarkan vtable di setiap unit terjemahan yang melihat definisi kelas polimorfik, tetapi itu biasanya tidak perlu berlebihan. Alternatif ( digunakan oleh gcc , dan mungkin oleh orang lain) adalah memilih satu unit terjemahan untuk menempatkan vtable, mirip dengan bagaimana Anda akan memilih file sumber tunggal untuk meletakkan anggota data statis kelas. Jika proses pemilihan ini gagal untuk memilih unit terjemahan apa pun, maka vtable menjadi referensi yang tidak ditentukan. Karenanya kesalahan, yang pesannya diakui tidak terlalu jelas.
Demikian pula, jika proses pemilihan memang memilih unit terjemahan, tetapi file objek itu tidak disediakan untuk linker, maka vtable menjadi referensi yang tidak ditentukan. Sayangnya, pesan kesalahan dapat menjadi kurang jelas dalam kasus ini daripada dalam kasus di mana proses seleksi gagal. (Terima kasih kepada para penjawab yang menyebutkan kemungkinan ini. Saya mungkin akan lupa kalau tidak.)
Proses pemilihan yang digunakan oleh gcc masuk akal jika kita mulai dengan tradisi mencurahkan file sumber (tunggal) untuk setiap kelas yang membutuhkan satu untuk implementasinya. Akan lebih baik untuk memancarkan vtable ketika mengkompilasi file sumber itu. Sebut saja itu tujuan kami. Namun, proses seleksi perlu bekerja bahkan jika tradisi ini tidak diikuti. Jadi alih-alih mencari implementasi seluruh kelas, mari kita mencari implementasi anggota kelas tertentu. Jika tradisi diikuti - dan jika anggota itu benar-benar dilaksanakan - maka ini mencapai tujuannya.
Anggota yang dipilih oleh gcc (dan berpotensi oleh kompiler lain) adalah fungsi virtual non-inline pertama yang bukan virtual murni. Jika Anda adalah bagian dari kerumunan yang mendeklarasikan konstruktor dan destruktor sebelum fungsi anggota lainnya, maka destruktor itu memiliki peluang bagus untuk dipilih. (Anda memang ingat membuat destructor virtual, kan?) Ada pengecualian; Saya berharap bahwa pengecualian yang paling umum adalah ketika definisi inline disediakan untuk destruktor dan ketika destruktor default diminta (menggunakan "
= default
").Cerdik mungkin memperhatikan bahwa kelas polimorfik diizinkan untuk memberikan definisi sebaris untuk semua fungsi virtualnya. Bukankah itu menyebabkan proses seleksi gagal? Itu dalam kompiler yang lebih tua. Saya telah membaca bahwa kompiler terbaru telah mengatasi situasi ini, tetapi saya tidak tahu nomor versi yang relevan. Saya bisa mencoba mencari ini, tetapi lebih mudah untuk kode di sekitarnya atau menunggu kompiler mengeluh.
Singkatnya, ada tiga penyebab utama kesalahan "referensi tidak ditentukan ke vtable":
Penyebab ini sendiri tidak cukup untuk menyebabkan kesalahan sendiri. Sebaliknya, ini adalah apa yang akan Anda atasi untuk menyelesaikan kesalahan. Jangan berharap bahwa dengan sengaja menciptakan salah satu dari situasi ini pasti akan menghasilkan kesalahan ini; ada persyaratan lain. Berharap bahwa menyelesaikan situasi ini akan menyelesaikan kesalahan ini.
(Oke, nomor 3 mungkin sudah cukup ketika pertanyaan ini diajukan.)
Bagaimana cara memperbaiki kesalahan?
Selamat datang kembali orang-orang yang melompat ke depan! :)
= 0
") dan yang definisinya Anda berikan (bukan "= default
").Contoh
Detail tentang apa yang harus dilakukan dapat bervariasi, dan kadang-kadang bercabang menjadi pertanyaan yang terpisah (seperti Apa itu referensi yang tidak ditentukan / kesalahan simbol eksternal yang tidak terselesaikan dan bagaimana cara memperbaikinya? ). Saya akan, bagaimanapun, memberikan contoh apa yang harus dilakukan dalam kasus tertentu yang mungkin membingungkan programmer yang lebih baru.
Langkah 1 menyebutkan memodifikasi kelas Anda sehingga memiliki fungsi tipe tertentu. Jika deskripsi fungsi itu melampaui kepala Anda, Anda mungkin berada dalam situasi yang ingin saya bahas. Ingatlah bahwa ini adalah cara untuk mencapai tujuan; itu bukan satu-satunya cara, dan dengan mudah bisa ada cara yang lebih baik dalam situasi spesifik Anda. Mari kita panggil kelasmu
A
. Apakah destruktor Anda dinyatakan (dalam definisi kelas Anda) sebagai salah satuatau
? Jika demikian, dua langkah akan mengubah destruktor Anda menjadi jenis fungsi yang kita inginkan. Pertama, ubah baris itu menjadi
Kedua, letakkan baris berikut dalam file sumber yang merupakan bagian dari proyek Anda (sebaiknya file dengan implementasi kelas, jika Anda memilikinya):
Itu membuat destruktor (virtual) Anda non-inline dan tidak dihasilkan oleh kompiler. (Jangan ragu untuk memodifikasi hal-hal agar lebih cocok dengan gaya pemformatan kode Anda, seperti menambahkan komentar header ke definisi fungsi.)
sumber
Ada banyak spekulasi yang terjadi di berbagai jawaban di sini. Di bawah ini saya akan memberikan kode yang cukup minimal yang mereproduksi kesalahan ini dan menjelaskan mengapa itu terjadi.
Kode Minimal Cukup untuk Mereproduksi Kesalahan Ini
IBase.hpp
Berasal.hpp
Derived.cpp
myclass.cpp
Anda dapat mengkompilasi ini menggunakan GCC seperti ini:
Anda sekarang dapat mereproduksi kesalahan dengan menghapus
= 0
di IBase.hpp. Saya mendapatkan kesalahan ini:Penjelasan
Perhatikan bahwa kode di atas tidak memerlukan destruktor virtual, konstruktor atau file tambahan lainnya agar kompilasi berhasil (walaupun Anda harus memilikinya).
Cara untuk memahami kesalahan ini adalah sebagai berikut: Linker mencari konstruktor dari IBase. Ini akan membutuhkannya untuk konstruktor Derived. Namun karena Derived mengganti metode dari IBase, ia memiliki vtable yang melekat padanya yang akan merujuk IBase. Ketika tautan mengatakan "referensi yang tidak terdefinisi ke vtable untuk IBase" pada dasarnya berarti Derived memiliki referensi vtable ke IBase tetapi tidak dapat menemukan kode objek IBase yang dikompilasi untuk dicari. Jadi intinya adalah bahwa kelas IBase memiliki deklarasi tanpa implementasi. Ini berarti metode dalam IBase dinyatakan sebagai virtual tetapi kami lupa menandainya sebagai virtual murni ATAU memberikan definisi.
Tip Perpisahan
Jika semuanya gagal maka salah satu cara untuk men-debug kesalahan ini adalah dengan membangun program minimal yang melakukan kompilasi dan kemudian terus mengubahnya sehingga sampai ke keadaan yang Anda inginkan. Di antaranya, terus kompilasi untuk melihat kapan mulai gagal.
Catatan tentang ROS dan sistem build Catkin
Jika Anda mengkompilasi set kelas di atas di ROS menggunakan sistem build catkin maka Anda perlu mengikuti baris di CMakeLists.txt:
Baris pertama pada dasarnya mengatakan bahwa kita ingin membuat executable bernama myclass dan kode untuk membangunnya dapat ditemukan file-file berikut. Salah satu file ini harus memiliki main (). Perhatikan bahwa Anda tidak harus menentukan file .hpp di mana saja di CMakeLists.txt. Anda juga tidak perlu menentukan Derived.cpp sebagai pustaka.
sumber
Saya baru saja menemukan penyebab lain untuk kesalahan ini yang dapat Anda periksa.
Kelas dasar mendefinisikan a fungsi virtual murni sebagai:
Dan subclass punya
Masalahnya adalah kesalahan ketik itu
"=0"
seharusnya berada di luar kurung:Jadi, jika Anda menggulir sejauh ini ke bawah, Anda mungkin tidak menemukan jawabannya - ini adalah hal lain yang perlu diperiksa.
sumber
Ini bisa terjadi dengan mudah jika Anda lupa menautkan ke file objek yang memiliki definisi.
sumber
GNU C ++ compiler harus membuat keputusan di mana harus meletakkan
vtable
jika Anda memiliki definisi fungsi virtual dari suatu objek yang tersebar di beberapa unit kompilasi (misalnya beberapa objek definisi fungsi virtual dalam file .cpp yang lain di file lain. file cpp, dan sebagainya).Compiler memilih untuk meletakkan
vtable
di tempat yang sama dengan di mana fungsi virtual pertama yang dideklarasikan didefinisikan.Sekarang jika Anda karena suatu alasan lupa untuk memberikan definisi untuk fungsi virtual pertama yang dideklarasikan dalam objek (atau keliru lupa untuk menambahkan objek yang dikompilasi pada tahap menghubungkan), Anda akan mendapatkan kesalahan ini.
Sebagai efek samping, harap dicatat bahwa hanya untuk fungsi virtual khusus ini Anda tidak akan mendapatkan kesalahan penghubung tradisional seperti Anda kehilangan fungsi foo .
sumber
Bukan untuk menyeberang pos tetapi. Jika Anda berurusan dengan warisan , google hit kedua adalah apa yang saya lewatkan, yaitu. semua metode virtual harus didefinisikan.
Seperti:
Lihat answare C ++ Undefined Reference ke vtable dan inheritance untuk detailnya. Baru sadar itu sudah disebutkan di atas, tapi sih mungkin bisa membantu seseorang.
sumber
Oke, solusi untuk ini adalah Anda mungkin telah kehilangan definisi. Lihat contoh di bawah ini untuk menghindari kesalahan kompilasi vtable:
sumber
CDasherComponent
memiliki badan penghancur? Jelas tidak di sini - pertanyaannya adalah apakah itu ada dalam file .cc.CDasherModule
harus secara eksplisit mendefinisikan destruktornyavirtual
.CGameModule
memiliki tambahan}
di akhir (setelah}; // for the class
).CGameModule
terkait dengan perpustakaan yang mendefinisikanCDasherModule
danCDasherComponent
?sumber
Mungkin kehilangan destruktor virtual adalah faktor penyebabnya?
sumber
Ini adalah hasil pencarian pertama bagi saya jadi saya pikir saya akan menambahkan hal lain untuk memeriksa: pastikan definisi fungsi virtual benar-benar ada di kelas. Dalam kasus saya, saya memiliki ini:
File tajuk:
dan dalam file .cc saya:
Ini harus dibaca
sumber
Tidak mungkin. Jelas
~CDasherModule() {}
tidak ada.sumber
Begitu banyak jawaban di sini, tetapi tak satu pun dari mereka yang membahas apa masalah saya. Saya memiliki yang berikut ini:
Dan di file lain (termasuk dalam kompilasi dan menautkan, tentu saja)
Yah ini tidak berhasil dan saya mendapat kesalahan yang dibicarakan semua orang. Untuk mengatasinya, saya harus memindahkan definisi Foo yang sebenarnya dari deklarasi kelas sebagai berikut:
Saya bukan guru C ++ jadi saya tidak bisa menjelaskan mengapa ini lebih benar tetapi itu memecahkan masalah bagi saya.
sumber
Jadi saya menggunakan Qt dengan Windows XP dan kompiler MinGW dan hal ini membuat saya gila.
Pada dasarnya moc_xxx.cpp dibuat kosong bahkan ketika saya ditambahkan
Q_OBJECT
Menghapus semua yang membuat fungsi virtual, eksplisit dan apa pun yang Anda duga tidak berfungsi. Akhirnya saya mulai menghapus baris demi baris dan ternyata sudah
Di sekitar file. Bahkan ketika #ifdef benar file moc tidak dihasilkan.
Jadi menghapus semua # jika masalah diperbaiki.
Hal ini tidak terjadi pada Windows dan VS 2013.
sumber
g++ *.cpp ...
. (Membutuhkan sesuatu yang cepat dan kotor tetapi qmake penuh dengan kesedihan.)Jika semuanya gagal, cari duplikasi. Saya salah arah oleh referensi awal eksplisit untuk konstruktor dan destruktor sampai saya membaca referensi di posting lain. Ini pun metode yang belum terselesaikan. Dalam kasus saya, saya pikir saya telah mengganti deklarasi yang menggunakan char * xml sebagai parameter dengan yang menggunakan const char * xml yang tidak perlu, tetapi sebagai gantinya, saya telah membuat yang baru dan meninggalkan yang lain di tempatnya.
sumber
Ada banyak kemungkinan yang disebutkan untuk menyebabkan kesalahan ini, dan saya yakin banyak dari mereka yang menyebabkan kesalahan. Dalam kasus saya, ada satu lagi definisi dari kelas yang sama, karena duplikasi file sumber. File ini dikompilasi, tetapi tidak ditautkan, sehingga linker mengeluh karena tidak dapat menemukannya.
Untuk meringkas, saya akan mengatakan bahwa jika Anda telah menatap kelas cukup lama dan tidak dapat melihat apa masalah yang mungkin menyebabkannya, cari masalah build seperti file yang hilang atau file yang digandakan.
sumber
Dalam kasus saya, saya menggunakan Qt dan telah mendefinisikan
QObject
subclass dalam filefoo.cpp
(bukan.h
). Cara mengatasinya adalah menambahkan#include "foo.moc"
di akhirfoo.cpp
.sumber
Saya pikir itu juga layak disebutkan bahwa Anda juga akan mendapatkan pesan ketika Anda mencoba untuk menautkan ke objek kelas mana pun yang memiliki setidaknya satu metode virtual dan tautan tidak dapat menemukan file. Sebagai contoh:
Foo.hpp:
Foo.cpp:
Dikompilasi dengan:
Dan main.cpp:
Dikompilasi dan dihubungkan dengan:
Memberikan kesalahan favorit kami:
Ini terjadi karena pemahaman saya karena:
Vtable dibuat per kelas pada waktu kompilasi
Linker tidak memiliki akses ke vtable yang ada di Foo.o
sumber
Saya mendapatkan kesalahan ini dalam skenario berikut
Pertimbangkan kasus di mana Anda telah mendefinisikan implementasi fungsi anggota suatu kelas dalam file header itu sendiri. File header ini adalah header yang diekspor (dengan kata lain, mungkin disalin ke beberapa yang umum / termasuk langsung dalam basis kode Anda). Sekarang Anda telah memutuskan untuk memisahkan implementasi fungsi anggota ke file .cpp. Setelah Anda memisahkan / memindahkan implementasinya ke .cpp, file header sekarang hanya memiliki prototipe fungsi anggota di dalam kelas. Setelah perubahan di atas, jika Anda membangun basis kode Anda, Anda mungkin mendapatkan kesalahan "referensi tidak terdefinisi untuk 'vtable ...".
Untuk memperbaiki ini, sebelum membangun, pastikan Anda menghapus file header (yang Anda buat perubahan) di direktori umum / sertakan. Juga pastikan Anda mengubah makefile Anda untuk mengakomodasi / menambahkan file .o baru yang dibangun dari file .cpp baru yang baru saja Anda buat. Ketika Anda melakukan langkah-langkah ini kompiler / tautan tidak akan lagi mengeluh.
sumber
Saya mendapatkan jenis kesalahan ini dalam situasi di mana saya mencoba menautkan ke suatu objek ketika saya membuat bug yang mencegah objek ditambahkan ke arsip.
Katakanlah saya punya libXYZ.a yang seharusnya memiliki bioseq.o di int tetapi tidak.
Saya mendapat kesalahan:
Ini berbeda dari semua hal di atas. Saya akan menyebut objek yang hilang ini dalam masalah arsip.
sumber
Mungkin juga Anda mendapatkan pesan seperti
jika Anda lupa mendefinisikan fungsi virtual kelas FakeClass1 saat Anda mencoba menautkan tes unit untuk SomeClass kelas lain.
Dan
Dalam hal ini saya sarankan Anda memeriksa palsu Anda untuk class1 sekali lagi. Anda mungkin menemukan bahwa Anda mungkin lupa mendefinisikan fungsi virtual
ForgottenFunc
di kelas palsu Anda.sumber
Saya mendapatkan kesalahan ini ketika saya menambahkan kelas kedua ke pasangan sumber / header yang ada. Dua header kelas dalam file .h yang sama, dan definisi fungsi untuk dua kelas dalam file .cpp yang sama.
Saya telah melakukan ini dengan sukses sebelumnya, dengan kelas-kelas yang dimaksudkan untuk bekerja sama secara erat, tetapi tampaknya sesuatu tidak menyukai saya saat ini. Masih tidak tahu apa, tetapi membaginya menjadi satu kelas per unit kompilasi memperbaikinya.
Upaya yang gagal:
_gui_icondata.h:
_gui_icondata.cpp:
Sekali lagi, menambahkan pasangan sumber / tajuk baru dan memotong / menempel kelas IconWithData kata demi kata di sana "hanya bekerja".
sumber
Kasus saya adalah satu konyol, saya memiliki tambahan
"
setelah#include
oleh kesalahan dan coba tebak?Saya telah menggaruk-garuk kepala dan wajah selama berjam-jam berkomentar fungsi virtual untuk melihat apakah ada yang berubah, dan akhirnya dengan menghapus ekstra
"
, semuanya sudah diperbaiki! Hal-hal semacam ini benar-benar perlu menghasilkan kesalahan kompilasi bukan kesalahan tautan.Secara ekstra
"
, maksud saya:sumber
Dalam kasus saya, saya memiliki kelas dasar bernama Person dan dua kelas turunan bernama Mahasiswa dan Profesor.
Bagaimana program saya diperbaiki adalah, 1. Saya membuat semua fungsi di kelas dasar
Pure Virtual.
2. Saya menggunakan semua destruktor virtual sebagaidefault ones.
sumber
Saya mendapatkan kesalahan ini hanya karena nama argumen konstruktor berbeda dalam file header dan file implementasi. Tanda tangan konstruktor adalah
dan apa yang saya tulis dalam implementasi dimulai dengan
jadi saya tidak sengaja mengganti "pset" dengan "hama". Kompilator mengeluh tentang yang satu ini dan dua konstruktor lain di mana tidak ada kesalahan sama sekali. Saya menggunakan g ++ versi 4.9.1 di bawah Ubuntu. Dan mendefinisikan destruktor virtual di kelas turunan ini tidak membuat perbedaan (didefinisikan di kelas dasar). Saya tidak akan pernah menemukan bug ini jika saya tidak menempelkan badan konstruktor di file header, sehingga mendefinisikan mereka di kelas.
sumber