Biểu tượng bên ngoài chưa được giải quyết trong các tệp đối tượng


180

Trong quá trình mã hóa trong Visual Studio, tôi đã gặp một lỗi biểu tượng bên ngoài chưa được giải quyết và tôi không biết phải làm gì. Tôi không biết điều gì sai. Bạn có thể vui lòng giải mã cho tôi? Tôi nên tìm loại lỗi nào?

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
Một biểu tượng chưa được giải quyết là một biểu tượng mà bạn đã khai báo ở đâu đó nhưng không bao giờ được xác định. Thông thường, điều đó có nghĩa là bạn đã bao gồm một số tệp tiêu đề của thư viện bên thứ ba nhưng không cho người liên kết biết nơi tìm các tệp .obj tương ứng cho thư viện.
deong

7
Lỗi khá phổ biến là bạn định nghĩa một hàm là độc lập và quên bộ chọn lớp trong tệp .cpp của mình : Bạn làm điều này (sai): void myFunc() { /* do stuff */ } Thay vì điều này (phải): void A::myFunc() { /* do stuff */ }
jave.web

Bạn cũng có thể thêm dấu ngoặc trực tiếp vào tệp tiêu đề nếu bạn không muốn xác định thêm trong tệp .cpp của mình, như thế : void myFunc() {};.
Patapoom

Câu trả lời:


303

Lỗi này thường có nghĩa là một số hàm có khai báo, nhưng không phải là định nghĩa.

Thí dụ:

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

// A.cpp

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

Trong trường hợp của bạn, định nghĩa không thể được tìm thấy. Vấn đề có thể là bạn đang bao gồm một tệp tiêu đề, mang đến một số khai báo hàm, nhưng bạn cũng vậy:

  1. không xác định các chức năng trong tệp cpp của bạn (nếu bạn tự viết mã này)
  2. không bao gồm tệp lib / dll có chứa các định nghĩa

Một lỗi phổ biến là bạn định nghĩa một hàm là độc lập và quên bộ chọn lớp, ví dụ: A::trong tệp .cpp của bạn :

Sai: void myFunc() { /* do stuff */ }
Phải: void A::myFunc() { /* do stuff */ }


2
Làm thế nào để bao gồm các tập tin lib nói trong dự án của tôi?
tmj

@tMJ Nó phụ thuộc vào môi trường bạn đang sử dụng. Tôi muốn tìm hướng dẫn trực tuyến hoặc trên trang web này.
Chris Morris

@ChrisMorris Định nghĩa của hàm không khả dụng không phải vì tôi không liên kết nó đúng hay gì đó. Nhưng, vì dll không có trong bộ nhớ và phải được tải thông qua một cuộc gọi LoadL Library. (FTR)
tmj

2
Lời khuyên cuối cùng chính xác là vấn đề ở đây. Tôi đã làm void myFunc() {}thay vì A::void myFunc() {}.
Charles

Rực rỡ trả lời. Tôi thực sự đã quên cả (1) và sau đó là phần A :: sau khi sao chép phương thức từ nơi khác.
RoG

24

Kiểm tra xem bạn có bao gồm tất cả các tệp nguồn trong giải pháp mà bạn đang tham chiếu không.

Nếu bạn không bao gồm tệp nguồn (và do đó là việc triển khai) cho lớp Fieldtrong dự án của bạn thì nó sẽ không được xây dựng và bạn sẽ không thể liên kết trong quá trình biên dịch.

Ngoài ra, có lẽ bạn đang sử dụng một thư viện tĩnh hoặc động và đã quên nói với trình liên kết về .libs?


3
Tham khảo các tập tin lib chính xác giải quyết vấn đề. Sử dụng Project-> Properties-> Linker-> General-> Thư viện bổ sung và Project-> Properties-> Linker-> Input-> Dependencies bổ sung để tham chiếu thư mục lib và các tệp lib
zak

11

Dường như thiếu một thư viện hoặc bao gồm, bạn có thể cố gắng tìm ra loại thư viện nào có getName, getType, v.v. và đặt nó vào tệp tiêu đề hoặc sử dụng #include.

Ngoài ra nếu những điều này xảy ra từ một thư viện bên ngoài, hãy đảm bảo bạn tham chiếu đến chúng trong tệp dự án của bạn. Ví dụ: nếu lớp này thuộc về abc.lib thì trong Visual Studio của bạn

  1. Nhấp vào Thuộc tính dự án.
  2. Chuyển đến Thuộc tính cấu hình, C / C ++, Tạo, xác minh bạn trỏ đến vị trí abc.lib trong Thư mục bao gồm bổ sung. Trong Trình liên kết, Đầu vào, đảm bảo bạn có abc.lib trong phần Phụ thuộc bổ sung.

9

Tôi vừa thấy vấn đề tôi không thể gọi một hàm từ tệp chính trong tệp .cpp, được khai báo chính xác trong tệp .h và được xác định trong tệp .c. Gặp phải một lỗi liên kết. Trong khi đó tôi có thể gọi hàm từ tệp .c thông thường. Có thể nó phụ thuộc vào quy ước cuộc gọi. Giải pháp là thêm các dòng preproc sau vào mỗi tệp .h:

#ifdef __cplusplus
extern "C"
{
#endif

và những điều này cuối cùng

#ifdef __cplusplus
}
#endif

7

Tôi đã có một lỗi trong đó dự án của tôi được biên dịch là dự án x64 . và tôi đã sử dụng một Thư viện được biên dịch là x86 .

Tôi đã biên dịch lại thư viện dưới dạng x64 và nó đã giải quyết nó.


5

đôi khi nếu một tệp tiêu đề mới được thêm vào và lỗi này bắt đầu xuất hiện do đó, bạn cũng cần thêm thư viện để thoát khỏi unresolved external symbol.

ví dụ:

#include WtsApi32.h

sẽ cần:

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

4

Tôi đã có cùng một lỗi liên kết, nhưng từ một dự án thử nghiệm đang tham khảo một dll khác. Phát hiện ra rằng sau khi thêm _declspec(dllexport)vào trước mỗi chức năng được chỉ định trong thông báo lỗi, liên kết đã hoạt động tốt.


3

Tôi tin rằng hầu hết các điểm liên quan đến nguyên nhân và biện pháp khắc phục đã được đề cập bởi tất cả những người đóng góp trong chủ đề này. Tôi chỉ muốn chỉ ra vấn đề 'bên ngoài chưa được giải quyết' của mình, nguyên nhân là do một kiểu dữ liệu được xác định là macro được thay thế khác với dự kiến, dẫn đến loại không chính xác được cung cấp cho hàm được đề cập và do hàm có loại không bao giờ được xác định, nó không thể được giải quyết. Cụ thể, trong C / C ++ -> Ngôn ngữ, có một thuộc tính được gọi là 'Treat WChar_t As Build in Type, đáng lẽ phải được định nghĩa là' Không (/ Zc: wchar_t-) 'nhưng không có trong trường hợp của tôi.


cảm ơn, điều này gây ra sự cố từ thiết lập của tôi ('Không (/ Zc: wchar_t-)')
Noypi Gilas

2

Ngoài câu trả lời xuất sắc của Chris Morris ở trên, tôi đã tìm thấy một cách rất thú vị mà bạn có thể nhận được lỗi tương tự này nếu bạn đang gọi một phương thức ảo chưa được đặt thành thuần túy nhưng không thực hiện riêng. Đó là cùng một lý do chính xác (trình biên dịch không thể tìm thấy cách triển khai phương thức và do đó kẻ gian), nhưng IDE của tôi đã không bắt lỗi này trong ít nhất.

ví dụ: đoạn mã sau sẽ gặp lỗi biên dịch với cùng thông báo lỗi:

//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;
    }
}

Tuy nhiên, việc thay đổi IamInterface myFunc () thành một phương thức ảo thuần túy (một phương thức "phải" được thực hiện, hơn một phương thức ảo là phương thức "có thể" bị ghi đè) sẽ loại bỏ lỗi biên dịch.

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

Hy vọng điều này sẽ giúp người StackOverFlow tiếp theo bước qua mã!



2

Hãy chắc chắn rằng bạn trang trí các tệp tiêu đề của bạn với

#ifndef YOUR_HEADER_H
#define YOUR_HEADER_H

// your header code here

#endif

Những điều tồi tệ - bao gồm điều này - có thể xảy ra nếu bạn không


8
Làm thế nào về việc sử dụng #pragma once?
Allen Linatoc

2

Một vấn đề khác có thể xảy ra (mà tôi mới gãi đầu một lúc):

Nếu bạn xác định các chức năng của mình là inline, thì tất nhiên, chúng sẽ được định nghĩa trong tiêu đề (hoặc một tệp nội tuyến ), chứ không phải là một cpp .
Trong trường hợp của tôi, chúng nằm trong một tệp nội tuyến, nhưng chỉ vì chúng là một triển khai cụ thể của nền tảng và một cpp bao gồm tệp inl tương ứng này thay vì một tiêu đề. Vâng, s ** t xảy ra.

Tôi nghĩ tôi cũng sẽ để nó ở đây, có lẽ ai đó cũng gặp phải vấn đề tương tự và tìm thấy nó ở đây.


1
Để bất kỳ ai hạ thấp điều này: Để lại ít nhất một nhận xét tại sao bạn nghĩ rằng câu trả lời là sai hoặc không hữu ích. Một downvote mà không có một bình luận là không có giá trị tốt nhất.
Johann Studanski

1

Tôi chỉ có một thời gian khó khăn với điều này. Tất cả mọi thứ đã được thiết lập hợp lý. Tôi đã khai báo một constructor nhưng không định nghĩa nó

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

Tôi gần như đập đầu vào bàn phím khi tôi quên một thứ gì đó quá cơ bản.


1

Tôi đang thực hiện một số C ++ lần đầu tiên sau một thời gian dài và tôi gặp lỗi này khi tôi quên thêm tiền tố ClassName :: cho định nghĩa hàm, vì đây là một chút duy nhất cho C ++. Vì vậy, hãy nhớ kiểm tra cho điều đó quá!


1

Một nguyên nhân có thể gây ra lỗi liên kết này cũng có thể là các inlinehàm được khai báo nhưng không được xác định trong tệp tiêu đề sau đó được đưa vào một nơi khác. Các hàm nội tuyến phải được xác định trong mỗi đơn vị dịch mà chúng được sử dụng.


0

ĐIỂM

Tôi đã có vấn đề này và giải quyết nó bằng cách sử dụng con trỏ. Tôi thấy rằng đây không phải là vấn đề của bạn nhưng tôi nghĩ tôi đã đề cập đến nó bởi vì tôi chắc chắn rằng nó đã ở đây khi tôi thấy điều này một giờ trước. Vấn đề của tôi là về việc khai báo một biến thành viên tĩnh mà không xác định nó (định nghĩa cần có sau một số thiết lập khác) và tất nhiên một con trỏ không cần định nghĩa. Sai lầm cơ bản không kém: P


3
Một ví dụ sẽ rất hữu ích ở đây.
moffeltje

0

Vấn đề của tôi là một bản sao chép không có cpptệp được định nghĩa trong đó. Điều này có thể rất khó hiểu vì Visual Studio có cpptệp trong dự án nhưng một cái gì đó hoàn toàn khác đang được xây dựng.


0

Vấn đề của tôi là: Tôi đã phải khai báo trước về lớp có ctor là "bên ngoài chưa được giải quyết".

Trong tệp mà tôi gặp lỗi, tôi phải đặt một cái gì đó như thế này:

#include "ClassB" 

class ClassB; // this solved the problem

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

Tất nhiên, dự án của tôi phức tạp hơn nhiều và đây chỉ là một ví dụ về đoạn trích. Ngoài ra khi sử dụng không gian tên, hãy khai báo chúng .


0

Chỉ mất vài giờ để thấy rằng vấn đề là tệp chính của tôi có phần mở rộng .cthay vì.cpp

:/


0

Một khả năng khác để kiểm tra, đó là vấn đề của tôi lần này.

Tôi đã thêm chức năng vào thư viện và đưa thư mục đầu ra của thư viện vào đường dẫn tìm kiếm.

Nhưng tôi cũng đã có một thư mục với phiên bản cũ hơn của thư viện được liệt kê trước đó, vì vậy VS đã sử dụng thư viện cũ và tất nhiên không tìm thấy chức năng mới.


0

Đảm bảo rằng bạn không cố gắng quá tải các toán tử chèn hoặc trích xuất dưới dạng các hàm nội tuyến. Tôi đã có vấn đề này và nó chỉ biến mất khi tôi loại bỏ từ khóa đó.


0

Điều gì đã gây ra nó trong trường hợp của tôi:

Tôi đã có một tập tin lớn Foo.cppmà không có Foo.h. Foo.cppbắt đầu như thế này:

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

Tôi đã xóa từ khóa "tĩnh" và thêm một từ Foo.hnày:

extern int var;

Bạn có thấy lỗi không?

Tôi hoàn toàn bỏ lỡ rằng var ban đầu được định nghĩa trong một không gian tên, bởi vì khai báo không gian tên được chôn trong mã khác. Cách khắc phục là thay đổi extern như thế này:

namespace NS {
     extern int var;
}

0

Một lý do có thể gây ra lỗi "Biểu tượng bên ngoài chưa được giải quyết" có thể là quy ước gọi hàm.

Đảm bảo rằng tất cả các tệp nguồn đang sử dụng cùng một tiêu chuẩn (.c hoặc .cpp) hoặc chỉ định quy ước gọi.

Mặt khác, nếu một tệp là tệp C (source.c) và một tệp khác là tệp .cpp và chúng liên kết đến cùng một tiêu đề, thì lỗi "biểu tượng bên ngoài chưa được giải quyết" sẽ bị ném, vì trước tiên hàm được định nghĩa là một hàm C cdecl, nhưng sau đó tệp C ++ sử dụng cùng một tiêu đề sẽ tìm kiếm một hàm C ++.

Để tránh "Lỗi ký hiệu bên ngoài chưa được giải quyết", hãy đảm bảo rằng quy ước gọi hàm được giữ giống nhau giữa các tệp sử dụng nó.


0

Tôi đến đây để tìm kiếm một lời giải thích có thể trước khi xem xét kỹ hơn các dòng trước lỗi liên kết. Hóa ra đó là một thực thi bổ sung mà tuyên bố toàn cầu bị thiếu!


0

Tôi đã có cùng một lỗi và tôi quản lý để tránh nó bằng cách thay thế ;bằng {}trong tệp tiêu đề.

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

Khi đó void xyzMethod();nó không muốn biên dịch.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.