Câu hỏi Lỗi bao gồm tệp (C ++): tham chiếu chưa xác định đến ______


Bất cứ khi nào tôi biên dịch cái gì đó # bao gồm một lớp do người dùng định nghĩa, tôi nhận được các lỗi biên dịch này luôn luôn trông giống như sau: main.cpp: undefined reference to Complex::Complex(double, double)

Tôi đã giảm vấn đề cho một tập hợp của ba tập tin cực kỳ trần: main.cpp, và ví dụ, Complex.h và Complex.cpp. Tôi vẫn nhận được lỗi tham chiếu không xác định. Tôi đang phát triển trong Code :: Blocks trên Windows nhưng tôi nhận được điều tương tự bằng cách sử dụng g + + trong Ubuntu. Lý do tại sao điều này xảy ra? Tôi đã thử xây dựng Complex.cpp trước main.cpp trong Code :: Blocks và tôi đã thử g++ main.cpp Complex.cpp nhiều như tôi đã thử g++ main.cpp. Cùng một lỗi mỗi lần.

/*======== main.cpp ========*/
#include "Complex.h"

int main()
{
    Complex A(1.0, 1.0);
    return 0;
}

/*======== Complex.h ========*/
#ifndef _COMPLEX_H
#define _COMPLEX_H

class Complex
{
    public:
    double x, y;
    Complex(double real, double imag);
};

#endif

/*======== Complex.cpp ========*/
#include "Complex.h"

Complex::Complex(double real, double imag)
{
    x = real;
    y = imag;
}

ed: bây giờ tôi nhận được các lỗi khác nhau vì vậy tôi phải làm điều gì đó hoàn toàn sai. Sử dụng cùng một mã như trên, tôi nhận được:

main.cpp: in function 'int main()':
main.cpp:5:5: error: 'Complex' was not declared in this scope
main.cpp:5:13: error: expected ';' before 'A'

Đây là kỳ quái. Tất cả mọi thứ đã làm việc trước đó khi tôi có lớp trong một tệp .cpp, nhưng đó là "thực hành xấu" vì vậy tôi đã chuyển các định nghĩa lớp của mình thành các tệp .h và lưu giữ tệp .cpp và bây giờ không có gì hoạt động.


7
2018-01-04 23:57


gốc


Ngoài ra, hãy chắc chắn thêm "-I" vào dòng biên dịch của bạn. Có lẽ ngay cả "-I", nếu các tệp .h của bạn nằm trong cùng một thư mục. - paulsm4
Nó làm việc cho tôi. Tôi vừa sao chép main.cpp, Complex.hvà Complex.cpp, và chạy g++ main.cpp Complex.cpp. Nó được tạo a.out bình thường. - ruakh
Làm việc cho tôi quá. @ paulsm4: không nên . nằm trong đường dẫn mặc định bao gồm? (lưu ý rằng anh ấy đang làm #include "...", không phải #include <...>) - Ricardo Cárdenes
Dán chính xác lỗi bạn nhận được khi bạn làm g++ main.cpp Complex.cpp. - David Schwartz
Bạn đã đăng mã thực tế chưa? Tôi không thể nhìn thấy bất cứ điều gì sai với mã này và g + + biên dịch mã tốt cho tôi. Mặc dù tôi đang sử dụng MacOS nhưng tôi nghi ngờ rằng tôi sẽ có một trải nghiệm khác nếu tôi sử dụng Linux. - Dietmar Kühl


Các câu trả lời:


Đó không phải là lỗi biên dịch, đó là lỗi liên kết. Bạn cần đảm bảo liên kết tất cả các đối tượng của bạn với nhau. Bạn có thể làm điều đó theo một vài cách:

g++ main.cpp Complex.cpp

Nên làm việc tốt (và làm ở đây khi tôi đã thử với ví dụ của bạn). Bạn cũng có thể thực hiện theo các bước:

g++ -c main.cpp
g++ -c Complex.cpp
g++ main.o Complex.o

7
2018-01-05 00:05



Trong câu hỏi, nó đã nói "Tôi đã thử g++ main.cpp Complex.cpp" - Aaron McDaid
@AaronMcDaid, nhưng rõ ràng là không, vì điều đó sẽ hiệu quả. Tôi cho rằng anh ta có thể quá đơn giản hóa ví dụ của mình, nhưng điều đó cũng không giúp anh ta có được câu trả lời đúng. - Carl Norum
Tôi đồng ý. Tôi đã upvoted câu trả lời của bạn vì nó có vẻ rõ ràng phải :-) Tôi cho rằng chúng tôi đang chờ đợi trên các chi tiết của thông báo lỗi chính xác. - Aaron McDaid
Có lẽ muốn một -o gắn cờ trên bước liên kết trừ khi bạn thích các chương trình của mình được đặt tên giống như a.out. - Mike DeSimone
@MikeDeSimone, tôi chỉ đang tìm kiếm cờ tối thiểu trống được đặt để tránh nhầm lẫn vấn đề. OP dường như không sử dụng bất kỳ -o cờ. - Carl Norum


Trong khi chúng ta còn lại trong bóng tối cho dù đây là mã thực sự (có lẽ không phải là nó hoạt động cho nhiều người khác), chúng ta hãy bình luận về mã một chút ... (điều này sẽ không có bất kỳ ảnh hưởng nào đối với lỗi liên kết)

  1. Tên bắt đầu bằng dấu gạch dưới theo sau là chữ cái viết hoa, ví dụ: _COMPLEX_H, được dành riêng cho việc thực hiện trình biên dịch C ++ và thư viện chuẩn C ++. Đừng sử dụng chúng.
  2. Biến thành viên được thực hiện tốt nhất private. Có rất ít khi cần thực hiện thành viên dữ liệu thực tế public (đôi khi nó là hợp lý để làm cho các thành viên không hoạt động public, ví dụ. một lớp sự kiện trong đó người dùng có thể đăng ký gọi lại, nhưng những hành vi này thường hoạt động như các hàm mặc dù chúng là các đối tượng kỹ thuật).
  3. Khởi tạo được thực hiện tốt nhất trong danh sách initializer thành viên. Đó là, hàm tạo sẽ trông giống như sau:

    Phức tạp :: Phức tạp (double real, double image):     x (thực),     y (tưởng tượng) { }

Cuối cùng, để mạo hiểm một vài người đoán được điều gì đang xảy ra với mã thực tế để gây ra vấn đề liên kết:

  1. Hàm khởi tạo được định nghĩa là inline. Rõ ràng, điều này sẽ không hoạt động trừ khi định nghĩa có thể nhìn thấy được khi hàm tạo được sử dụng.
  2. Tuyên bố của Complex bằng cách nào đó đã làm cho nó thành một không gian tên không tên và do đó định nghĩa xảy ra để xác định một lớp khác với lớp được thấy bởi main.cpp.

1
2018-01-05 00:13