สัญลักษณ์ภายนอกที่ไม่ได้รับการแก้ไขในไฟล์วัตถุ


180

ระหว่างการเข้ารหัสใน Visual Studio ฉันพบข้อผิดพลาดของสัญลักษณ์ภายนอกที่ไม่ได้รับการแก้ไขและฉันไม่รู้ว่าจะทำอย่างไร ฉันไม่รู้ว่ามีอะไรผิดปกติ คุณช่วยถอดรหัสฉันหน่อยได้ไหม ฉันควรหาข้อผิดพลาดประเภทใด

1>Form.obj : error LNK2019: unresolved external symbol "public: class Field * __thiscall Field::addField(class Field *)" (?addField@Field@@QAEPAV1@PAV1@@Z) referenced in function "public: void __thiscall Form::parse(class std::basic_stringstream<char,struct std::char_traits<char>,class std::allocator<char> > &)" (?parse@Form@@QAEXAAV?$basic_stringstream@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z)
1>Form.obj : error LNK2019: unresolved external symbol "public: virtual void __thiscall Field::parse(class std::basic_stringstream<char,struct std::char_traits<char>,class std::allocator<char> > &)" (?parse@Field@@UAEXAAV?$basic_stringstream@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) referenced in function "public: __thiscall InputField::InputField(class std::basic_stringstream<char,struct std::char_traits<char>,class std::allocator<char> > &)" (??0InputField@@QAE@AAV?$basic_stringstream@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z)
1>Form.obj : error LNK2001: unresolved external symbol "public: virtual void __thiscall Field::prompt(void)" (?prompt@Field@@UAEXXZ)
1>Form.obj : error LNK2001: unresolved external symbol "public: virtual class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __thiscall Field::getName(void)" (?getName@Field@@UAE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@XZ)
1>Form.obj : error LNK2001: unresolved external symbol "public: virtual class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __thiscall Field::getType(void)" (?getType@Field@@UAE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@XZ)
1>Form.obj : error LNK2001: unresolved external symbol "public: virtual void __thiscall Field::describe(void)" (?describe@Field@@UAEXXZ)
1>C:\Users\tomy\Documents\Visual Studio 2010\Projects\zapoctovkac++\Debug\zapoctovkac++.exe : fatal error LNK1120: 6 unresolved externals

26
สัญลักษณ์ที่ไม่ได้รับการแก้ไขคือสัญลักษณ์ที่คุณได้ประกาศไว้ แต่ไม่เคยนิยามไว้ โดยปกติแล้วหมายความว่าคุณได้รวม # header ไฟล์ของห้องสมุดบุคคลที่สามไว้แล้ว แต่ไม่ได้บอก linker ว่าจะหาไฟล์. obj ที่เกี่ยวข้องสำหรับไลบรารีได้อย่างไร
deong

7
ข้อผิดพลาดทั่วไปที่ค่อนข้างสวยคือคุณกำหนดฟังก์ชั่นเป็นแบบสแตนด์อโลนและลืมตัวเลือกคลาสในไฟล์. cppของคุณ: คุณทำสิ่งนี้ (ผิด): void myFunc() { /* do stuff */ } แทนที่จะเป็นแบบนี้ (ขวา): void A::myFunc() { /* do stuff */ }
jave.web

นอกจากนี้คุณยังสามารถเพิ่มวงเล็บของคุณโดยตรงในส่วนหัวของไฟล์ถ้าคุณไม่ต้องการที่จะกำหนดมันมากขึ้นในการ CPP void myFunc() {};แฟ้มของคุณเช่นว่า:
Patapoom

คำตอบ:


303

ข้อผิดพลาดนี้มักจะหมายความว่าฟังก์ชั่นบางอย่างมีการประกาศ แต่ไม่ได้นิยาม

ตัวอย่าง:

// A.hpp
class A
{
public:
  void myFunc(); // Function declaration
};

// A.cpp

// Function definition
void A::myFunc()
{
  // do stuff
}

ในกรณีของคุณไม่พบคำจำกัดความ ปัญหาอาจเป็นได้ว่าคุณกำลังรวมไฟล์ส่วนหัวซึ่งมีการประกาศฟังก์ชั่นบางอย่าง แต่คุณอาจ:

  1. ไม่ได้กำหนดฟังก์ชั่นในไฟล์ cpp ของคุณ (ถ้าคุณเขียนรหัสนี้ด้วยตัวเอง)
  2. ห้ามรวมไฟล์ lib / dll ที่มีคำจำกัดความ

ข้อผิดพลาดทั่วไปคือคุณกำหนดฟังก์ชันเป็นแบบสแตนด์อโลนและลืมตัวเลือกคลาสเช่น A::ในไฟล์. cppของคุณ:

ผิด: void myFunc() { /* do stuff */ }
ใช่: void A::myFunc() { /* do stuff */ }


2
จะรวมไฟล์ lib ดังกล่าวในโครงการของฉันได้อย่างไร
tmj

@tMJ มันขึ้นอยู่กับสภาพแวดล้อมที่คุณใช้ ฉันต้องการค้นหาบทเรียนออนไลน์หรือบนเว็บไซต์นี้
Chris Morris

@ChrisMorris คำจำกัดความของฟังก์ชั่นไม่สามารถใช้งานได้เพราะฉันไม่ได้เชื่อมโยงมันอย่างถูกต้องหรือบางสิ่งบางอย่าง แต่เนื่องจาก dll ไม่ได้อยู่ในหน่วยความจำและจะต้องโหลดผ่านการเรียก LoadLibrary (FTR)
tmj

2
คำแนะนำสุดท้ายคือปัญหาที่นี่ ผมทำแทนvoid myFunc() {} A::void myFunc() {}
ชาร์ลส์

คำตอบที่ยอดเยี่ยม ฉันลืมทั้ง (1) จริง ๆ แล้วส่วน A :: หลังจากคัดลอกวิธีมาจากที่อื่น
RoG

24

ตรวจสอบว่าคุณได้รวมไฟล์ต้นฉบับทั้งหมดไว้ในโซลูชันของคุณที่คุณอ้างอิงหรือไม่

หากคุณไม่รวมไฟล์ต้นฉบับ (และการนำไปใช้งาน) สำหรับคลาส Fieldในโครงการของคุณจะไม่ถูกสร้างขึ้นและคุณจะไม่สามารถลิงก์ระหว่างการรวบรวม

หรือบางทีคุณอาจใช้ห้องสมุดแบบคงที่หรือแบบไดนามิกและลืมบอก linker เกี่ยวกับ.libs?


3
การอ้างอิงไฟล์ lib ที่ถูกต้องช่วยแก้ไขปัญหาได้ ใช้ Project-> Properties-> Linker-> General-> Directories Library เพิ่มเติมและ Project-> Properties-> Linker-> Input-> Dependencies เพิ่มเติมเพื่ออ้างถึงไดเร็กทอรี lib และไฟล์ lib
zak

11

ดูเหมือนจะหายไปห้องสมุดหรือรวมคุณสามารถพยายามที่จะคิดออกว่าระดับของไลบรารีของคุณที่มี getName, getType ฯลฯ ... #includeและใส่ว่าในไฟล์ส่วนหัวหรือใช้

นอกจากนี้หากสิ่งเหล่านี้เกิดขึ้นจากไลบรารีภายนอกตรวจสอบให้แน่ใจว่าคุณอ้างอิงถึงพวกเขาในไฟล์โครงการของคุณ ตัวอย่างเช่นถ้าคลาสนี้เป็นของ abc.lib ใน Visual Studio ของคุณ

  1. คลิกที่คุณสมบัติของโครงการ
  2. ไปที่คุณสมบัติการกำหนดค่า, C / C ++, สร้าง, ตรวจสอบว่าคุณชี้ไปที่ตำแหน่ง abc.lib ภายใต้ไดเรกทอรีรวมเพิ่มเติม ภายใต้ Linker ป้อนข้อมูลตรวจสอบให้แน่ใจว่าคุณมี abc.lib ภายใต้การพึ่งพาเพิ่มเติม

9

ฉันเพิ่งเห็นปัญหาที่ฉันไม่สามารถเรียกใช้ฟังก์ชั่นจาก main ในไฟล์. cpp, ประกาศอย่างถูกต้องในไฟล์. h และกำหนดไว้ในไฟล์. c พบข้อผิดพลาด linker ในขณะเดียวกันฉันสามารถเรียกใช้ฟังก์ชั่นจากไฟล์. c ปกติได้ อาจเป็นไปได้ว่ามันขึ้นอยู่กับการประชุมสาย วิธีแก้ไขคือการเพิ่มบรรทัด preproc ต่อไปนี้ในไฟล์. h ทุกไฟล์:

#ifdef __cplusplus
extern "C"
{
#endif

และสิ่งเหล่านี้ในที่สุด

#ifdef __cplusplus
}
#endif

7

ฉันมีข้อผิดพลาดที่โครงการของฉันถูกรวบรวมเป็นโครงการx64 และผมเคยใช้ห้องสมุดที่รวบรวมเป็นx86

ฉันได้คอมไพล์ไลบรารีใหม่เป็น x64 และแก้ไขได้


5

unresolved external symbolบางครั้งถ้าไฟล์ส่วนหัวใหม่จะถูกเพิ่มและข้อผิดพลาดนี้เริ่มมาเนื่องจากการที่คุณจะต้องเพิ่มห้องสมุดเช่นกันที่จะกำจัด

ตัวอย่างเช่น:

#include WtsApi32.h

จะต้อง:

#pragma comment(lib, "Wtsapi32.lib") 

4

ฉันมีข้อผิดพลาดลิงค์เดียวกัน แต่จากโครงการทดสอบซึ่งอ้างอิง dll อื่น พบว่าหลังจากเพิ่ม _declspec(dllexport)ด้านหน้าของแต่ละฟังก์ชั่นที่ระบุไว้ในข้อความแสดงข้อผิดพลาดลิงค์ทำงานได้ดี


3

ฉันเชื่อว่าประเด็นส่วนใหญ่เกี่ยวกับสาเหตุและการเยียวยาได้รับการคุ้มครองโดยผู้มีส่วนร่วมทั้งหมดในหัวข้อนี้ ฉันต้องการชี้ให้เห็นถึงปัญหา 'ภายนอกที่ไม่ได้รับการแก้ไข' ของฉันมันเกิดจากประเภทข้อมูลที่กำหนดเป็นแมโครที่ได้รับการแทนที่แตกต่างจากที่คาดไว้ซึ่งส่งผลให้ประเภทที่ไม่ถูกต้องถูกส่งไปยังฟังก์ชันที่เป็นปัญหา ไม่เคยถูกกำหนดมันไม่สามารถแก้ไขได้ โดยเฉพาะอย่างยิ่งภายใต้ C / C ++ -> ภาษามีคุณลักษณะที่เรียกว่า 'Treat WChar_t As Built in Type ซึ่งควรได้รับการกำหนดเป็น' ไม่ (/ Zc: wchar_t-) 'แต่ไม่ได้อยู่ในกรณีของฉัน


ขอบคุณสิ่งนี้ทำให้เกิดปัญหาจากการตั้งค่าของฉัน ('ไม่ (/ Zc: wchar_t-)')
Noypi Gilas

2

นอกเหนือจากคำตอบที่ยอดเยี่ยมโดย Chris Morris ข้างต้นฉันพบวิธีที่น่าสนใจมากที่คุณจะได้รับข้อผิดพลาดเดียวกันนี้หากคุณกำลังเรียกใช้วิธีเสมือนที่ไม่ได้ตั้งค่าให้บริสุทธิ์ แต่ไม่ได้ใช้งานจริง มันเป็นเหตุผลเดียวกันที่แน่นอน (คอมไพเลอร์ไม่สามารถหาการใช้งานของวิธีการและดังนั้น crooks) แต่ IDE ของฉันไม่ได้จับความผิดนี้ในบิตที่น้อยที่สุด

ตัวอย่างเช่นรหัสต่อไปนี้จะได้รับข้อผิดพลาดในการรวบรวมพร้อมกับข้อความแสดงข้อผิดพลาดเดียวกัน:

//code testing an interface
class test
{
   void myFunc(); 
}

//define an interface
class IamInterface
{
    virtual void myFunc();
}

//implementation of the interface
class IamConcreteImpl
{
    void myFunc()
    {
       1+1=2;
    }
}

อย่างไรก็ตามการเปลี่ยน IamInterface myFunc () เป็นวิธีเสมือนจริง (วิธีที่ "ต้อง" จะถูกนำมาใช้ซึ่งกว่าวิธีเสมือนซึ่งเป็นวิธีที่ "สามารถ" ถูกแทนที่) จะกำจัดข้อผิดพลาดในการรวบรวม

//define an interface
class IamInterface
{
    virtual void myFunc() = 0;
}

ความหวังนี้จะช่วยให้ผู้ StackOverFlow คนต่อไปก้าวผ่านโค้ด!



2

ตรวจสอบให้แน่ใจว่าคุณตกแต่งไฟล์ส่วนหัวด้วย

#ifndef YOUR_HEADER_H
#define YOUR_HEADER_H

// your header code here

#endif

สิ่งที่ไม่ดีรวมถึงสิ่งนี้อาจเกิดขึ้นได้หากคุณไม่ทำ


8
วิธีการเกี่ยวกับการใช้งาน#pragma once?
Allen Linatoc

2

ยังมีอีกปัญหาที่เป็นไปได้ (ที่ฉันเพิ่งเกาหัวของฉันเกี่ยวกับเวลา):

หากคุณกำหนดฟังก์ชั่นของคุณเป็นinlineพวกเขา-แน่นอน! -have จะถูกกำหนดไว้ในส่วนหัว (หรืออินไลน์แฟ้ม) ไม่CPP
ในกรณีของฉันพวกเขาอยู่ในไฟล์ inline แต่เพียงเพราะพวกเขาเป็นการใช้งานเฉพาะแพลตฟอร์มและcppรวมไฟล์inl ที่สอดคล้องกันนี้... แทนที่จะเป็นส่วนหัว ใช่เกิดขึ้น **

ฉันคิดว่าฉันจะออกจากที่นี่ด้วยบางทีคนอื่นอาจพบปัญหาเดียวกันและพบที่นี่


1
หากต้องการคนที่ลงคะแนนสิ่งนี้: อย่างน้อยก็แสดงความคิดเห็นว่าทำไมคุณคิดว่าคำตอบนั้นผิดหรือไม่เป็นประโยชน์ downvote ที่ไม่มีความคิดเห็นนั้นไม่มีค่าที่ดีที่สุด
โยฮันน์ Studanski

1

ฉันเพิ่งมีช่วงเวลาที่ยากลำบากกับสิ่งนี้ ทุกอย่างถูกตั้งค่าอย่างมีเหตุผล ฉันประกาศตัวสร้าง แต่ไม่ได้กำหนดไว้

class SomeClass
{
   SomeClass();  // needs the SomeClass::SomeClass(){} function defined somewhere, even here
}

ฉันเกือบกระแทกหัวของฉันบนแป้นพิมพ์ของฉันเมื่อฉันลืมสิ่งที่ประถมศึกษา


1

ฉันกำลังทำ C ++ เป็นครั้งแรกในระยะเวลานานและฉันได้รับข้อผิดพลาดนี้เมื่อฉันลืมเพิ่มคำนำหน้า ClassName :: สำหรับคำจำกัดความของฟังก์ชั่นเนื่องจากนี่เป็นเอกลักษณ์ของ C ++ เล็กน้อย ดังนั้นอย่าลืมตรวจสอบสิ่งนั้นด้วย!


1

สาเหตุหนึ่งที่เป็นไปได้ของข้อผิดพลาด linker นี้ยังสามารถเป็นinlineฟังก์ชั่นที่มีการประกาศ แต่ไม่ได้กำหนดไว้ในไฟล์ส่วนหัวที่รวมอยู่ที่อื่นแล้ว ต้องกำหนดฟังก์ชั่นอินไลน์ในทุกหน่วยการแปลที่ใช้


0

ชี้

ฉันมีปัญหานี้และแก้ไขได้โดยใช้ตัวชี้ ฉันเห็นว่านี่ไม่ใช่ปัญหาของคุณ แต่ฉันคิดว่าฉันจะพูดถึงมันเพราะฉันแน่ใจว่าหวังว่าจะได้รับที่นี่เมื่อฉันเห็นสิ่งนี้ชั่วโมงที่ผ่านมา ปัญหาของฉันเกี่ยวกับการประกาศตัวแปรสมาชิกแบบคงที่โดยไม่กำหนด (ความหมายจำเป็นต้องมาหลังจากเซ็ตอัพอื่น ๆ ) และแน่นอนตัวชี้ไม่จำเป็นต้องมีคำนิยาม ข้อผิดพลาดเบื้องต้นที่เท่าเทียมกัน: P


3
ตัวอย่างจะเป็นประโยชน์อย่างมากที่นี่
moffeltje

0

ปัญหาของฉันคือ sconscript ไม่มีcppไฟล์ที่กำหนดไว้ในนั้น สิ่งนี้อาจสร้างความสับสนได้มากเนื่องจาก Visual Studio มีcppไฟล์อยู่ในโครงการ


0

ปัญหาของฉันคือฉันต้องทำการประกาศล่วงหน้าของคลาสที่ ctor เป็น "ภายนอกที่ไม่ได้รับการแก้ไข"

ในไฟล์ที่ฉันได้รับข้อผิดพลาดฉันต้องใส่อะไรแบบนี้:

#include "ClassB" 

class ClassB; // this solved the problem

class ClassA{
    void foo(){
        ClassB* tmp = new ClassB();
        // ...
    }
};

แน่นอนโครงการของฉันมีความซับซ้อนมากขึ้นและนี่เป็นเพียงตัวอย่างตัวอย่าง นอกจากนี้เมื่อใช้ namespaces, ประกาศพวกเขาเช่นกัน


0

เพิ่งใช้เวลาสองสามชั่วโมงเพื่อค้นหาว่าปัญหาคือไฟล์หลักของฉันมีส่วนขยาย.cแทน.cpp

:/


0

อีกความเป็นไปได้ที่จะตรวจสอบมันเป็นปัญหาของฉันในครั้งนี้

ฉันได้เพิ่มฟังก์ชั่นลงในไลบรารีและรวมโฟลเดอร์เอาท์พุทของห้องสมุดไว้ในพา ธ การค้นหา

แต่ฉันก็มีโฟลเดอร์ที่มีไลบรารี่ที่เก่ากว่าในรายการก่อนหน้านี้ดังนั้น VS จึงใช้ไลบรารี่เก่าและแน่นอนว่าไม่ได้หาฟังก์ชั่นใหม่


0

ตรวจสอบให้แน่ใจว่าคุณไม่ได้พยายามใส่ตัวดำเนินการแทรกหรือตัวแยกข้อมูลเป็นฟังก์ชันอินไลน์ ฉันมีปัญหานี้และหายไปเมื่อฉันลบคำหลักนั้น


0

สิ่งที่เกิดขึ้นในกรณีของฉัน:

ฉันมีไฟล์ขนาดใหญ่ที่Foo.cppไม่มี Foo.h Foo.cppเริ่มเช่นนี้

// ... 100 LOC here ...
namespace NS {
// ... 100 more LOC here ...
static int var;

ฉันลบคำหลัก "คงที่" และเพิ่มFoo.hด้วย:

extern int var;

คุณเห็นข้อผิดพลาดหรือไม่?

ฉันพลาดทั้งหมดว่า var เดิมถูกกำหนดไว้ในเนมสเปซเพราะการประกาศเนมสเปซถูกฝังในโค้ดอื่น การแก้ไขคือการเปลี่ยนภายนอกเช่นนี้:

namespace NS {
     extern int var;
}

0

สาเหตุที่เป็นไปได้สำหรับข้อผิดพลาด "สัญลักษณ์ภายนอกที่ไม่ได้รับการแก้ไข" อาจเป็นรูปแบบการเรียกใช้ฟังก์ชัน

ตรวจสอบให้แน่ใจว่าไฟล์ต้นฉบับทั้งหมดใช้มาตรฐานเดียวกัน (.c หรือ. cpp) หรือระบุแบบแผนการโทร

มิฉะนั้นหากไฟล์หนึ่งไฟล์เป็นไฟล์ C (source.c) และไฟล์อื่นเป็นไฟล์. cpp และลิงก์ไปยังส่วนหัวเดียวกันข้อผิดพลาด "สัญลักษณ์ภายนอกที่ไม่ได้รับการแก้ไข" จะถูกโยนทิ้งเนื่องจากฟังก์ชันจะถูกกำหนดเป็น ฟังก์ชั่น C cdecl แต่ไฟล์ C ++ ที่ใช้ส่วนหัวเดียวกันจะมองหาฟังก์ชั่น C ++

เพื่อหลีกเลี่ยง "ข้อผิดพลาดสัญลักษณ์ภายนอกที่ไม่ได้รับการแก้ไข" ตรวจสอบให้แน่ใจว่ารูปแบบการเรียกใช้ฟังก์ชันนั้นยังคงเหมือนเดิมระหว่างไฟล์ที่ใช้งาน


0

ฉันมาที่นี่เพื่อค้นหาคำอธิบายที่เป็นไปได้ก่อนที่จะดูบรรทัดที่อยู่ข้างหน้าข้อผิดพลาดของลิงเกอร์ มันกลับกลายเป็นว่าปฏิบัติการเพิ่มเติมที่การประกาศทั่วโลกหายไป!


0

ฉันเพิ่งมีข้อผิดพลาดเดียวกันและฉันจัดการเพื่อหลีกเลี่ยงได้โดยแทนที่;ด้วย{}ในไฟล์ส่วนหัว

#ifndef XYZ_h
#define XYZ_h
class XYZ
{
    public:
    void xyzMethod(){}
}
#endif

เมื่อก่อนvoid xyzMethod();มันไม่ต้องการรวบรวม

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.