PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : C++: undefinied reference to vtables



stefan-tiger
31-05-2005, 14:10
Hallo, versuche grad ein simples Programm zu schreiben.

Es gibt eine Klasse "Koerper" und eine davon abgeleitete "Kreis".


Leider erhalte ich einen Linkerfehler:

bash-2.05b$ qmake -project && qmake && make && make clean && ./geo
g++ -c -pipe -Wall -W -march=athlon -O2 -pipe -DQT_NO_DEBUG -I/usr/qt/3/mkspecs/linux-g++ -I. -I. -Isrc -I/usr/qt/3/include -o kreis.o src/kreis.cpp
g++ -c -pipe -Wall -W -march=athlon -O2 -pipe -DQT_NO_DEBUG -I/usr/qt/3/mkspecs/linux-g++ -I. -I. -Isrc -I/usr/qt/3/include -o main.o src/main.cpp
g++ -o geo kreis.o main.o -L/usr/qt/3/lib -L/usr/X11R6/lib -lqt -lXext -lX11 -lm
kreis.o(.text+0x128): In function `Kreis::~Kreis [not-in-charge]()':
: undefined reference to `vtable for Koerper'
kreis.o(.text+0x138): In function `Kreis::~Kreis [in-charge]()':
: undefined reference to `vtable for Koerper'
kreis.o(.text+0x148): In function `Kreis::~Kreis [in-charge deleting]()':
: undefined reference to `vtable for Koerper'
kreis.o(.gnu.linkonce.r._ZTI5Kreis+0x8): undefined reference to `typeinfo for Koerper'
collect2: ld returned 1 exit status
make: *** [geo] Fehler 1

Hier der Code:

koerper.h


#ifndef KOERPER_H
#define KOERPER_H

class Koerper
{
public:
Koerper() { id=0; }
Koerper(int ID) { id=ID; }
int GetID() { return id; }
virtual void definiere() {};
virtual double flaeche();
virtual double umfang();
virtual void zeichne();
virtual void bewege(double x, double y);
virtual ~Koerper() {}
protected:
int id;
} ;

#endif


kreis.h


#ifndef KREIS_H
#define KREIS_H
#include "koerper.h"
#include "point.h"

#define PI 3.14159265

class Kreis : public Koerper
{
public:
Kreis();
Kreis(Point p,double r);
void definiere(Point p,double r);
double flaeche();
double umfang();
double bogen(double alpha);
double sektor(double alpha);
void zeichne();
void bewege(double x, double y);
~Kreis();
private:
double radius;
Point koords;
} ;

#endif


kreis.cpp


#include "kreis.h"
#include <iostream>
using namespace std;

Kreis::Kreis()
{
koords = Point();
radius = 1;
}

Kreis::Kreis(Point p,double r)
{
koords = p;
radius = r;
}

Kreis::~Kreis()
{}


void Kreis::definiere(Point p,double r)
{
koords = p;
radius = r;
}

double Kreis::flaeche()
{
return (PI*radius*radius);
}

double Kreis::umfang()
{
return (PI*2*radius);
}

double Kreis::bogen(double alpha)
{
return (2*PI/360*alpha*radius);
}

double Kreis::sektor(double alpha)
{
return (PI/360*alpha*radius*radius);
}

void Kreis::zeichne()
{
cout << "zeichne Kreis x: " << koords.x << " y: " << koords.y << " Radius: " << radius << endl;
}

void Kreis::bewege(double x, double y)
{
koords.x+=x;
koords.y+=y;
}

locus vivendi
31-05-2005, 14:51
Wenn das dein ganzer Code ist, dann hast du nicht alle Memberfunktionen von Koerper definiert, z.B. flaeche().

stefan-tiger
31-05-2005, 15:19
Wenn das dein ganzer Code ist, dann hast du nicht alle Memberfunktionen von Koerper definiert, z.B. flaeche().

flaeche() ist doch virtual. d.h. das verhalten soll in abgeleiteten Klassen definiert werden.

Sorry, diese virtual Geschichten sind neu für mich.

anda_skoa
31-05-2005, 15:46
Du brauchst in Koerper "pure virtuals", also ohne direkte Implementation

zB


virtual double flaeche() = 0;


Ciao,
_

locus vivendi
31-05-2005, 16:28
flaeche() ist doch virtual. d.h. das verhalten soll in abgeleiteten Klassen definiert werden.
Genaugenommen hat sich der Linker ja auch nicht über undefinierte Referenzen auf Funktionen beschwert, sonderen eben über die "vtable" für die Klasse. Wenn ich das richtig im Kopf hab, sieht das nämlich beim GCC so aus, das die "vtable" in der Übersetzungseinheit erzeugt wird, in der die erste virtuelle, nicht-inline Funktion definiert wird. Genaueres findest du irgendwo im GCC Texinfo-Manual unter "Vague Linkage".

stefan-tiger
31-05-2005, 18:16
Du brauchst in Koerper "pure virtuals", also ohne direkte Implementation

zB


virtual double flaeche() = 0;


Ciao,
_

Habe dann mal alle virtual Funktionen so gemacht -> gleicher Fehler.

peschmae
31-05-2005, 20:49
Ich hab mal alles rausgeschmissen was von points-Zeugs abhängt. Kompiliert bei mir (mit den pure virtual funktionen als solche deklariert).

Kannst du nochmal den (ganzen) Code posten?

MfG Peschmä

stefan-tiger
01-06-2005, 07:13
Ich hab mal alles rausgeschmissen was von points-Zeugs abhängt. Kompiliert bei mir (mit den pure virtual funktionen als solche deklariert).

Kannst du nochmal den (ganzen) Code posten?

MfG Peschmä

Im Anhang.

locus vivendi
01-06-2005, 08:48
Jetzt fehlt noch die Definition für den Destruktor von Koerper. Auch wenn du Funktionen als Pure-Virtual markierst, musst du sie dennoch implementieren wenn sie z.B. gerufen werden. Und der Destruktor von Koerper wird ja gerufen. Nämlich implizit wenn wenn Objekte vom abgeleiteten Typ zerstört werden.

stefan-tiger
01-06-2005, 11:52
Jetzt fehlt noch die Definition für den Destruktor von Koerper. Auch wenn du Funktionen als Pure-Virtual markierst, musst du sie dennoch implementieren wenn sie z.B. gerufen werden. Und der Destruktor von Koerper wird ja gerufen. Nämlich implizit wenn wenn Objekte vom abgeleiteten Typ zerstört werden.

Tatsächlich, danke sehr.
Alleerdings glaube ich, daß ich es so schon hatte.

Auch wenns für erfahrene Programmierer schrecklich aussieht, meine Klasse sieht nun so aus:


class Koerper
{
public:
Koerper() { id=0; }
Koerper(int ID) { id=ID; }
int GetID() { return id; }
virtual double flaeche() { return 0.0; }
virtual double umfang() { return 0.0; }
virtual void zeichne() {}
virtual void bewege(double x, double y) {x=y;}
virtual ~Koerper() {}
protected:
int id;
} ;

So lässt es sich kompilieren, das x=y wegen dem warning von gcc.

Was das =0 macht, was "pure virtual" genannt wird lass ich mal weg bis ich es in einem Kapital kennengelernt hab.

Danke nochmal.