Seite 1 von 1

[gelöst] Funktion in header -> multiple definition of...

Verfasst: 18. Juni 2011 17:27
von Spinoza
Hi,
habe momentan ein kurioses Problem. Ich möchte ein QSet eines enums in/von einem QDataStream schreiben/lesen können. Da Qt von sich aus nicht weiß, dass enums auch nur unsigned ints sind schreibe ich also den Operator<< und >> für dieses enum selbst, und zwar im header(*).

Minimalbeispiel:

Code: Alles auswählen

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QDataStream>
#include <QSet>

enum TestEnum {teEins, teZwei};

QDataStream &operator>>(QDataStream &ds, TestEnum &te)
{
  quint16 v;
  ds >> v;
  te = (TestEnum)v;
  return ds;
}

QDataStream &operator<<(QDataStream &ds, const TestEnum &te)
{ (...) }

namespace Ui {
    class MainWindow;
}

class MainWindow : public QMainWindow {
(...)
};

#endif // MAINWINDOW_H
Interessanterweise bekomme ich den Fehler:
/usr/include/qt4/QtCore/qdatastream.h:219: multiple definition of `operator>>(QDataStream&, TestEnum&)'
mainwindow.h:13: first defined here
/usr/include/qt4/QtCore/qglobal.h:1372: multiple definition of `operator>>(QDataStream&, TestEnum&)'
mainwindow.h:13: first defined here
:-1: error: collect2: ld returned 1 exit status
obwohl ich ja ein mehrfaches einfügen dieses Headers mittels der defines verhindere. Und was hat überhaupt qglobal.h damit zutun? in Zeile 1372 steht dort code, der nichts offensichtliches mit QDataStream zutun hat.

Jemand 'ne Idee?

(*): Der Fehler tritt natürlich nicht auf, wenn ich die Operatoren im Header nur deklariere und in der .cpp dann implementiere. Da ich diese Operatoren in mehreren Sourcen verwenden möchte, hätte ich sie gerne, inklusive der enum-definition, in einer kompakten header-datei, die ich dann wo immer ich sie benötige einfach includen kann - deswegen auch die Implementierung in einem header.

Verfasst: 18. Juni 2011 18:54
von franzf
Die include-guards sind nur interessant für den Präprozessor, bei dir beschwert sich aber der Linker. Wenn du in mehreren .cpps den Header einbindest, existiert in jeder dieser .cpps eine Definition der Funktion. Werden diese .cpps kompiliert und die Object-Files zu einem Executable gelinkt, findet der Linker (ld bei dir) in jeder der .cpps eine Definition -> multiple definitions.

Lösung: Die Funktionsdefinition als "inline" markieren -> inline davor schreiben. (Googlen wenn du nicht weißt was inline sein soll).

Verfasst: 18. Juni 2011 19:21
von Spinoza
Ah, wieder was gelernt, vielen Dank.
Hat ein explizites inline also doch noch eine Daseinsberechtigung. ;)