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

Tankard

Treue Seele

  • »Tankard« ist der Autor dieses Themas

Beiträge: 192

Beruf: Student, Hardware- und Softwareentwicklung als wissenschaftliche Hilfskraft

  • Private Nachricht senden

1

03.06.2014, 15:43

[C++] Problem mit Interface (LNK2019)

Moin,

ich muss derzeit eine alte C++ Software umgestalten. Dabei müssen unter anderem verschiedene Kameras angesprochen werden. Dazu wollte ich eine Manager-Klasse machen, in welcher die Bilder entsprechend synchron oder zeitversetzt angefordert werden können. Da verschiedene Kameras zum Einsatz kommen, wollte ich ein Interface benutzen. Dieses sieht bis jetzt so aus:

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#pragma once

#include <memory>

#include <qobject.h>

#include "Types.h"


class IToFCamera : public QObject
{
    Q_OBJECT

public:
    virtual ~IToFCamera() = 0;

signals:
    void newImageAvailable();

    // Public Functions
public:
    virtual bool isConnected() = 0;
    virtual bool connect() = 0;
    virtual bool requestImage() = 0;
    virtual bool acquireImage() = 0;
    virtual CloudPtr getImage() = 0;
};


Nun wollte ich dieses Interface in einer Klasse implementieren:

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#pragma once

#include "IToFCamera.h"

class O3DCamera : public IToFCamera
{
    Q_OBJECT

public:
    // Constructors / Destructors
    O3DCamera();
    virtual ~O3DCamera();

    // Public Functions
public:
    virtual bool isConnected();
    virtual bool connect();
    virtual bool requestImage();
    virtual bool acquireImage();
    virtual CloudPtr getImage();
};


Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include "O3DCamera.h"


O3DCamera::O3DCamera()
{
}


O3DCamera::~O3DCamera()
{
}

bool O3DCamera::isConnected()
{
    return true;
}

bool O3DCamera::connect()
{
    return true;
}

bool O3DCamera::requestImage()
{
    return true;
}

bool O3DCamera::acquireImage()
{
    return true;
}

CloudPtr O3DCamera::getImage()
{
    return CloudPtr(new PointCloudRGB);
}


Dies resultiert allerdings in folgendem Linkerfehler:

Zitat


Fehler 3 error LNK2019: Verweis auf nicht aufgelöstes externes Symbol ""public: virtual __thiscall IToFCamera::~IToFCamera(void)" (??1IToFCamera@@UAE@XZ)" in Funktion ""public: virtual __thiscall O3DCamera::~O3DCamera(void)" (??1O3DCamera@@UAE@XZ)". [...]\O3DCamera.obj <ProjektName>


Ich habe ehrlich gesagt noch nie mit Interfaces in C++ gearbeitet und habe gerade keine Ahnung was ich gegen das nicht aufgelöste Symbol von dem virtuellem Destruktor des Interfaces machen kann.

Wie benutze ich so ein Interface richtig?

2

03.06.2014, 16:16

Ich bin mir weder sicher, noch ein Profi auf dem Gebiet, aber darf der Destruktor virtual sein?
Vererben kann man den ja eh nicht, oder?

3

03.06.2014, 16:17

C++ kennt an sich den Begriff "Interface" nicht. Ein Interface in C++ ist nichts anderes als eine Klasse oder Struktur, die ausschließlich virtuelle Member-Funktionen enthält. Dennoch ist es eine eigenständige Klasse, deren virtuelle Memberfunktionen nur in der VT überschrieben werden und ließe sich somit auch als Base-Class-With-Virtual-Member-Functions bezeichnen.
Somit ist "virtual ~IToFCamera() = 0;" nicht nötig, aber möglich, benötigt dann aber noch immer eine, wenn auch leere, Definition:

C-/C++-Quelltext

1
2
3
4
5
6
struct IToFCamera
{
  virtual ~IToFCamera() = 0;
};

IToFCamera::~IToFCamera() {}
EnvisionGame(); EnableGame(); AchieveGame(); - Visionen kann man viele haben. Sie umzusetzen und auf das Ergebnis stolz zu sein ist die eigentliche Kunst.

Architekt

Community-Fossil

Beiträge: 2 481

Wohnort: Hamburg

Beruf: Student

  • Private Nachricht senden

4

03.06.2014, 17:09

Ich bin mir weder sicher, noch ein Profi auf dem Gebiet, aber darf der Destruktor virtual sein?
Vererben kann man den ja eh nicht, oder?

Kann und sollte.
Ein kleines Beispiel zur Demonstration:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class A {
public:
/*  virtual */~A() {
        std::cout << "DTor A" << std::endl;
    }
};

class B : public A {
public:
    virtual ~B() {
        std::cout << "DTor B" << std::endl;
    }
};

int main() {
    A* b = new B();
    delete b;
    return 0;
}


Ausgabe mit vorhandenem virtual:

Zitat


DTor B
DTor A

Ausgabe mit auskommentierten virtual (wie es halt oben steht):

Zitat


DTor A


Wieso das so ist, lass ich mal dich rausfinden. :search:
Der einfachste Weg eine Kopie zu entfernen ist sie zu löschen.
- Stephan Schmidt -

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »Architekt« (03.06.2014, 18:47)


patrick246

Treue Seele

Beiträge: 328

Wohnort: nahe Heilbronn/BW

Beruf: TG Profil Informatik-Schüler

  • Private Nachricht senden

5

03.06.2014, 17:28

Nicht anders herum? ;)

Architekt

Community-Fossil

Beiträge: 2 481

Wohnort: Hamburg

Beruf: Student

  • Private Nachricht senden

6

03.06.2014, 17:43

Nicht anders herum? ;)

Probier es doch aus.
Der einfachste Weg eine Kopie zu entfernen ist sie zu löschen.
- Stephan Schmidt -

patrick246

Treue Seele

Beiträge: 328

Wohnort: nahe Heilbronn/BW

Beruf: TG Profil Informatik-Schüler

  • Private Nachricht senden

7

03.06.2014, 17:46

Ausgabe mit auskommentiertem virtual ( /* virtual */):

Quellcode

1
DTor A

http://ideone.com/LilqM8

Ausgabe mit vorhandenem virtual:

Quellcode

1
2
DTor B
DTor A

http://ideone.com/bMgERj

Klar, wenn man das "wie es halt oben steht" nimmt, dann ist es richtig, trotzdem ist es oben auskommentiert.

Architekt

Community-Fossil

Beiträge: 2 481

Wohnort: Hamburg

Beruf: Student

  • Private Nachricht senden

8

03.06.2014, 18:46

Ok ich passe die Formulierung an, die scheint nicht eindeutig zu sein, geb ich dir Recht.
Der einfachste Weg eine Kopie zu entfernen ist sie zu löschen.
- Stephan Schmidt -

Tankard

Treue Seele

  • »Tankard« ist der Autor dieses Themas

Beiträge: 192

Beruf: Student, Hardware- und Softwareentwicklung als wissenschaftliche Hilfskraft

  • Private Nachricht senden

9

03.06.2014, 21:37

Somit ist "virtual ~IToFCamera() = 0;" nicht nötig, aber möglich, benötigt dann aber noch immer eine, wenn auch leere, Definition:

C-/C++-Quelltext

1
2
3
4
5
6
struct IToFCamera
{
  virtual ~IToFCamera() = 0;
};

IToFCamera::~IToFCamera() {}

Ich bin davon ausgegangen, dass für rein virtuelle Funktionen (dazu habe ich auch den Destruktor gezählt) keine Implementierung nötig ist. Aber OK, dann werde ich noch eine leere Implementierung hinzufügen.

Werbeanzeige