2016-09-07 12 views
5

Sau khi tạo lớp sau, quá trình biên dịch không thành công với nhiều lỗi "biểu tượng trùng lặp". Các lỗi thực tế không phải là rất mô tả:Tại sao điều này không đánh dấu quá tải nhà điều hành là nội tuyến gây ra lỗi định nghĩa trùng lặp?

"biểu tượng trùng lặp __Zeq .... trong: /Users/myusername/Library/Developer/Xcode/DerivedData/MyProject-asdfasfasdf..../Build/Intermediates/ MyProject.build/Debug-iphonesimulator/MyTarget.build/Objects-normal/i386/MyClass.o "

thông điệp tương tự ở trên xuất hiện trong nhiều lớp khác nhau, và xuất hiện ở phần cuối của biên soạn, vì vậy tôi don Không biết vấn đề là gì.

Tôi đã kiểm tra như sau:

  1. Lớp học sử dụng này, bao gồm các tập tin Listening.hpp.
  2. Định nghĩa duy nhất cho lớp này, có trong tệp này.

Sự cố có thể là gì?

#ifndef Listening_hpp 
#define Listening_hpp 
#include <stdio.h> 
#include "EAction.hpp" 

class Listening{ 
private: 
    int _emitterId; 
    int _listenerId; 
    std::string _eventName; 
    EAction* _actionToTake; //not owned. 

protected: 

public: 

    Listening(int emitterId,int listenerId,std::string eventName,EAction* actionToTake) : _emitterId(emitterId),_listenerId(listenerId),_eventName(eventName){ 
     _actionToTake = actionToTake; 
    } 

    int getEmitterId()const{ 
     return _emitterId; 
    } 

    int getListenerId()const{ 
     return _listenerId; 
    } 

    std::string getEventName()const{ 
     return _eventName; 
    } 

    EAction* getAction()const{ 
     return _actionToTake; 
    } 
}; 

bool operator==(const Listening &first,const Listening &other) 
{ 
    bool result = false; 

    if(first.getEmitterId() == other.getEmitterId()){ 
     if(first.getListenerId() == other.getListenerId()){ 
      if(first.getEventName() == other.getEventName()){ 
       if (first.getAction() == other.getAction()) { 
        result = true; 
       } 
      } 
     } 
    } 

    return result; 
} 

bool operator!=(const Listening &first,const Listening &other) 
{ 
    bool result = !(first == other); 

    return result; 
} 

#endif /* Listening_hpp */ 

EAction.hpp

#ifndef EAction_hpp 
#define EAction_hpp 

#include <stdio.h> 
class EAction{ 
private: 
protected: 
public: 

    virtual std::vector<std::size_t> seedList() = 0; 
}; 
#endif /* EAction_hpp */ 

EDIT: Chỉnh sửa tiêu đề - Tôi nghĩ rằng điều này có thể giúp những người có một lỗi định nghĩa trùng lặp vì những lý do khác bỏ qua câu trả lời này.

+2

Vì bạn đã xác định toán tử 'operator ==' và '! =' Trong tệp tiêu đề! – Brian

+3

Nhận xét trước khi anh chàng Hy Lạp đánh dấu điều này là trùng lặp chính xác của một megathread –

+0

@Brian Bạn có thể giải thích tại sao đó là một vấn đề? Tôi mới đến với C++, nhưng có kinh nghiệm với các ngôn ngữ lập trình khác, vì vậy không biết những điều cơ bản này ... –

Trả lời

6

Các chức năng miễn phí trong file header hoặc phải được đánh dấu inline, hoặc thay đổi chỉ có tờ khai trong tiêu đề:

inline bool operator==(const Listening &first,const Listening &other) 
{ 

và tương tự cho operator!=.

Vấn đề ban đầu là bất kỳ đơn vị nào bao gồm tệp tiêu đề này sẽ có tệp đối tượng chứa một bản sao của operator==. Sau đó, các mối liên kết nhìn thấy điều này và không biết cái nào có nghĩa là một trong những quyền. inline có thể được coi là chỉ thị liên kết để nói "Tất cả các chức năng này đều giống nhau, chỉ cần chọn một". Link to more detailed answers.

Vấn đề tương tự cũng không xảy ra với các cơ quan chức năng của thành viên lớp vì các phần tử được viết bên trong định nghĩa lớp hoàn toàn là inline.


lịch sử lưu ý: Nguyên, inline là chủ yếu một chỉ thị tối ưu hóa. Tuy nhiên, các trình biên dịch ngày nay đủ thông minh để đưa ra các quyết định tối ưu hóa riêng của chúng; do đó, việc sử dụng chính của inline bây giờ là những gì đã từng là hiệu ứng phụ: để tránh nhiều lỗi định nghĩa khi có một chức năng trong một tiêu đề.


BTW, bạn có thể viết return bla;, thay vì gán bla cho một biến bool và vân vân.

+0

Cảm ơn .. nhưng bạn có thể giải thích tại sao không? Tôi biết nó hoạt động, nhưng tại sao phiên bản không nội tuyến của tôi không hoạt động? Tôi là một người mới bắt đầu với C++ vì vậy tôi không biết nhiều điều cơ bản về C++, và sẽ không có bất kỳ hoặc thậm chí làm thế nào để tìm ra những lỗi trong trường hợp này là. –

+1

@John khi bạn không đánh dấu một hàm là 'inline', trình biên dịch sẽ làm cho nó có sẵn để sử dụng trong các tệp nguồn khác. Nếu bạn có nhiều hơn một được biên dịch thành các tệp nguồn khác nhau, trình liên kết giả định chúng phải khác và tạo ra lỗi khi tìm thấy nhiều hàm có cùng tên. –

+0

Ah! Cảm ơn câu trả lời đó. Tôi luôn luôn tự hỏi - nhưng không bao giờ có xung quanh để tìm kiếm những gì nội tuyến là cho - Tôi nghe nói đó là một số loại tối ưu hóa trình biên dịch nhưng không bao giờ nghĩ về nó. Điều mà cả bạn và Mark đang nói đều có ý nghĩa ... bi kịch học các ngôn ngữ khác trước C++ ...: D –

Các vấn đề liên quan