Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

Schorsch

Supermoderator

  • »Schorsch« ist der Autor dieses Themas

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

1

20.08.2014, 13:39

[gelöst] C++ include functions in cpp file, linker error

Hey,
ich merke ich verlerne C++ immer mehr und mittlerweile bereiten mir doch einfachste Dinge Kopfzerbrechen. Für mein aktuelles anliegen ergibt C++ als Sprache aber nun mal Sinn und von daher muss ich da durch.
Ich habe im Prinzip eine Header-Datei die Funktionen bereit stellen soll. Hier Beispielsweise "worker.h":

C-/C++-Quelltext

1
2
3
4
5
#pragma once

bool doWork() {
    return true;
}


Nun habe ich zwei Klassen die in ihren Implementierungen darauf zugreifen sollen, hier einfach mal "Consumer1" und "Consumer2":
Consumer1.h: (Consumer2.h sieht im Prinzip genau so aus)

C-/C++-Quelltext

1
2
3
4
5
6
7
#pragma once
class Consumer1
{
public:
    Consumer1(void);
    ~Consumer1(void);
};


Consumer1.cpp: (Consumer2.cpp sieht im Prinzip genau so aus)

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
#include "Consumer1.h"

#include "worker.h"

Consumer1::Consumer1(void)
{
    doWork();
}


Consumer1::~Consumer1(void)
{
}


main.cpp:

C-/C++-Quelltext

1
2
3
4
5
6
7
#include "Consumer1.h"
#include "Consumer2.h"

int main() {
    Consumer1 cons;
    Consumer2 cons2;
}


Fehlermeldung ist:

Quellcode

1
2
1>Consumer2.obj : error LNK2005: "bool __cdecl doWork(void)" (?doWork@@YA_NXZ) ist bereits in Consumer1.obj definiert.
1>H:\development\c++\LinkerTest\Debug\LinkerTest.exe : fatal error LNK1169: Mindestens ein mehrfach definiertes Symbol gefunden.


Ich bin mir einfach nicht sicher wie ich das lösen soll. Ich dachte durch #pragma once würde ich mehrfache Einbindung im Code schon mal unterbinden. Nun binde ich die Datei ja in den CPP Files ein. Ich bin mir nicht mehr ganz sicher, aber die werden glaube ich eh gesondert übersetzt und dann macht die doppelte Definition ja auch Sinn. Wie umgehe ich das jetzt aber. Wenn ich andere Header inkludiere gibt es ja auch keine Probleme?
Habe auch Include-Guards mit define versucht. Selbes Ergebnis. Was ja nach meiner Logik auch durchaus Sinn ergibt.

Ich bin mittlerweile einfach zu verwöhnt von höheren Sprachen und merke dass ich auch einiges an Hintergrundwissen nicht mehr habe. An sich handelt es sich hier ja um eine Kleinigkeit.
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »Schorsch« (21.08.2014, 11:02)


TrommlBomml

Community-Fossil

Beiträge: 2 117

Wohnort: Berlin

Beruf: Software-Entwickler

  • Private Nachricht senden

2

20.08.2014, 13:41

Ich würde vermuten wenn du doWork() in dem Header als Prototypen hast und in einer separaten cpp implementierst, dann gehts problemlos ;)

Hast aber mein Beileid, geht mir teilweise genauso :).

Schorsch

Supermoderator

  • »Schorsch« ist der Autor dieses Themas

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

3

20.08.2014, 13:53

Danke TrommlBomml:)
Die Idee hatte ich soweit auch, empfand es aber als unschön. Ich möchte nicht zu jeder Header Datei eine cpp Datei anlegen müssen. Zumindest musste ich das bis jetzt eigentlich nie. Möglicherweise arbeite ich auch grad einfach falsch mit der Sprache.
Jokestar hat mir grad im Chat unter die Arme gegriffen. Wenn ich die Funktion (doWork) als "inline" deklariere funktionierts. So richtig schön finde ich das immer noch nicht, aber immerhin klappt es jetzt. Höre mir aber gern auch andere Vorschläge an.
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

ExCluSiv3

Frischling

Beiträge: 61

Wohnort: Düsseldorf

Beruf: Fachinformatiker - Ausbildung

  • Private Nachricht senden

4

20.08.2014, 13:57

probiers mal mit anderen Include Guards also im sinne von:

C-/C++-Quelltext

1
2
3
4
5
6
#ifndef _WORKER_H_
#define _WORKER_H_

[...]

#endif


Ich weis nicht wie zuverlässig das pragma ist, aber mit denen sollte man eher vorsichtig sein.

Edit: Ob das Inline jetzt wirklich eine Lösung ist sei mal dahin gestellt, würde eher sagen du umschiffst das Problem damit anstatt es wirklich zu Lösen.

TrommlBomml

Community-Fossil

Beiträge: 2 117

Wohnort: Berlin

Beruf: Software-Entwickler

  • Private Nachricht senden

5

20.08.2014, 13:59

Mittlerweile ist pragma once voll ok und wird auch vom GCC unterstützt. Soll sogar wenn ich mich richtig erinnere etwas performanter sein, weil der compiler die defines selber vergibt.

ExCluSiv3

Frischling

Beiträge: 61

Wohnort: Düsseldorf

Beruf: Fachinformatiker - Ausbildung

  • Private Nachricht senden

6

20.08.2014, 14:02

Das mag sein, jedoch hatte ich auch schon solche Probleme die durch das pragma once ausgelöst wurden und durch normale defines beseitigt wurden.

Edit: Sorry hatte übersehen, dass die Definition auch in der Header ist, in dem Fall bringen die Guards natürlich nichts :D nichts desto trotz bleiben die pragmas (selbst mit VS 2013) mit Vorsicht zu genießen

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »ExCluSiv3« (20.08.2014, 14:17)


Evrey

Treue Seele

Beiträge: 245

Beruf: Weltherrscher

  • Private Nachricht senden

7

20.08.2014, 14:06

Wenn du Funktionen in Headern implementieren willst, musst du sie als inline deklarieren. Dadurch wird es dem Compiler erlaubt, Dublikate dieser Funktion in mehreren Übersetzungs-Einheiten zu haben.

Edit: Die mehrfache Einbindung wird im Übrigen nur pro Übersetzungseinheit verhindert.

C-/C++-Quelltext

1
2
3
4
int main(int _argc, char** _argv) noexcept {
  asm volatile("lock cmpxchg8b %eax");
  return 0;
} // ::main
(Dieses kleine Biest vermochte einst x86-Prozessoren lahm zu legen.)

=> Und er blogt unter Hackish.Codes D:

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

8

20.08.2014, 14:26

Exakt, dein Stichwort lautet: inline.

9

20.08.2014, 14:30

Vielleicht noch zur Erklärung: http://stackoverflow.com/a/10847368
EnvisionGame(); EnableGame(); AchieveGame(); - Visionen kann man viele haben. Sie umzusetzen und auf das Ergebnis stolz zu sein ist die eigentliche Kunst.

10

20.08.2014, 18:52

Pass aber auf jeden Fall auf, dass die Signatur eindeutig ist. Das kann sonst zu sehr interessanten Ergebnissen führen...
»Steef« hat folgende Datei angehängt:
  • header_test.tgz (425 Byte - 46 mal heruntergeladen - zuletzt: 01.05.2024, 10:03)
"Theory is when you know something, but it doesn’t work. Practice is when something works, but you don’t know why. Programmers combine theory and practice: Nothing works and they don’t know why." - Anon

Werbeanzeige