2016-09-07 3 views
5

Nach dem Erstellen der folgenden Klasse schlägt die Kompilierung mit vielen "doppelten Symbol" -Fehlern fehl. Der tatsächliche Fehler ist nicht sehr aussagekräftig:Warum führt dies nicht zu einer Überlastung des Operators als Inline, die zu einem doppelten Definitionsfehler führt?

„doppeltes Symbol __Zeq .... in: /Users/myusername/Library/Developer/Xcode/DerivedData/MyProject-asdfasfasdf..../Build/Intermediates/ MyProject.build/Debug-iphonesimulator/MyTarget.build/Objects-normal/i386/MyClass.o "

die oben gleiche Meldung erscheint für viele verschiedene Klassen, und am Ende der Compilation erscheint, so dass ich don Ich weiß nicht, was das Problem ist.

ich folgende überprüft haben:

  1. Klassen, die diese verwenden, schließen die Listening.hpp Datei.
  2. Die einzige Definition für diese Klasse ist in dieser Datei.

Was kann das Problem sein?

#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: den Titel Edited - Ich denke, das Menschen, die eine doppelte Definitionsfehler haben helfen können aus anderen Gründen diese Antwort ignorieren.

+2

Weil Sie 'operator ==' und 'operator! =' In der Header-Datei definiert haben! – Brian

+3

Kommentieren, bevor griechischer Typ dies als exaktes Duplikat eines Megathreads markiert –

+0

@Brian Können Sie erklären, warum das ein Problem ist? Ich bin neu in C++, habe aber Erfahrung mit anderen Programmiersprachen, kenne also diese grundlegenden Dinge nicht ... –

Antwort

6

Die freien Funktionen in der Header-Datei muss entweder inline markiert werden oder geändert nur Erklärungen im Header zu haben:

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

und in ähnlicher Weise für operator!=.

Das ursprüngliche Problem ist, dass jede Einheit einschließlich dieser Header-Datei seine Objektdatei eine Kopie der operator== enthält. Dann sieht der Linker das und weiß nicht, welcher der richtige ist. Die inline kann als eine Linker-Anweisung gedacht werden, um zu sagen "Alle diese Funktionen sind die gleichen, wählen Sie nur eine". Link to more detailed answers.

Das gleiche Problem trat nicht mit den Klassenmember-Funktionskörpern auf, da solche in die Klassendefinition geschriebenen Körper implizit inline sind.


Historische Anmerkung: Ursprünglich inline war in erster Linie eine Optimierung Richtlinie. Heute sind Compiler jedoch schlau genug, selbst Optimierungsentscheidungen zu treffen. so ist die primäre Verwendung von inline jetzt, was einmal der sekundäre Effekt war: um mehrere Definitionsfehler zu vermeiden, wenn eine Funktion in einem Header vorhanden ist.


BTW, können Sie return bla; schreiben, statt bla zu einer bool Variablen zugewiesen und so weiter.

+0

Danke .. aber können Sie erklären warum? Ich weiß, es funktioniert, aber warum funktionierte meine Nicht-Inline-Version nicht? Ich bin ein Anfänger zu C++, also kenne ich nicht viele grundlegende Dinge über C++, und hätte auch nicht einmal, wie man den Fehler in diesem Fall herausfinden kann. –

+1

@John Wenn Sie eine Funktion nicht als "Inline" markieren, stellt der Compiler sie für die Verwendung in anderen Quelldateien zur Verfügung. Wenn Sie mehr als einen in verschiedene Quelldateien kompiliert haben, nimmt der Linker an, dass sie unterschiedlich sein müssen und generiert den Fehler, wenn er mehr als eine Funktion mit demselben Namen findet. –

+0

Ah! Danke für diese Antwort. Ich habe mich immer gewundert - aber ich kam nie dazu, nachzusehen, wofür Inline gedacht war - ich habe gehört, dass es eine Art Compiler-Optimierung war, aber ich habe nie darüber nachgedacht. Was sowohl Sie als auch Mark sagen, ergibt Sinn ... die Tragik des Erlernens anderer Sprachen vor C++ ...: D –

Verwandte Themen