UNIX Socket FAQ

A forum for questions and answers about network programming on Linux and all other Unix-like systems

You are not logged in.

  • Index
  • » C++
  • » Problems with pure virtual functions under gcc

#1 2008-03-03 07:54 AM

vedlajsia
Guest

Re: Problems with pure virtual functions under gcc

Hi i have this code:

player.h  -> is for API definition

#ifndef PLAYER_H
#define PLAYER_H

#include <string>

class player{
public:
  virtual std::string get_title(void) = 0;
  virtual std::string get_artist(void) = 0;
  virtual std::string get_time_string(void) = 0;
  virtual unsigned long long int get_time_ms(void) = 0;
};

#endif

And this class which uses player as API reference:
amarok.h

#ifndef AMAROK_H
#define AMAROK_H

#include "player.h"

class player_amarok : public player{
public:
  std::string get_title(void);
  std::string get_artist(void);
  std::string get_time_string(void);
  unsigned long long int get_time_ms(void);
};

#endif

All functions are implemented in amarok.cpp. My problem shows up when i try to add one more public virtual function so the code looks like this:

#ifndef PLAYER_H
#define PLAYER_H

#include <string>

class player{
public:
  virtual std::string get_title(void) = 0;
  virtual std::string get_artist(void) = 0;
  virtual std::string get_time_string(void) = 0;
  virtual unsigned long long int get_time_ms(void) = 0;
[color="Red"]  virtual int is_running(void) = 0;[/color]
};

#endif

and

#ifndef AMAROK_H
#define AMAROK_H

#include "player.h"

class player_amarok : public player{
public:
  std::string get_title(void);
  std::string get_artist(void);
  std::string get_time_string(void);
  unsigned long long int get_time_ms(void);
[color="Red"]  int is_running(void);[/color]
};

#endif

I compile it as:

g++ -c -o amarok.o amarok.cpp

My problem is that when i try to compiile it after adding a is_running() function it shows me this error when linking:

[color="Red"]main.o: In function `main':
main.cpp:(.text+0x1168): undefined reference to `vtable for player_amarok'
collect2: ld returned 1 exit status[/color]

When i remove is_running again it compiles right.(is_running is not used at this time anywhere) I really dont know where the problem could be. PLEASE HELP ME. :confused:

P.S.: when i look at amarok.o in midight commanders editor there is really vtable items missing when i add is_running function.

P.S2: linking is done this way:

g++ -o exec main.o xwindow.o players/amarok.o -O3 -L. -lSPL -lconfig++

P.S3: is_running is already implemented in amarok.cpp
P.S4: :confused:  PLEASE HELP ME :confused:

#2 2008-03-03 07:04 PM

mlampkin
Administrator
From: Sol 3
Registered: 2002-06-12
Posts: 911
Website

Re: Problems with pure virtual functions under gcc

I know you said you have all functions implemented in amarok.cpp including the one that appears to be causing the issue...

Are you only seeing a single ( 1 ) vtable missing / undefined reference when you add the new function... and if so - are you certain the body of player_amarok::is_running( void ) is actually declared fully / properly i.e. with the class player_amarok:: prefix etc. ? 

On a side note and something that really isn't "necessary" but usually when I am providing the definition for / overriding a virtual function... I typically prefix the definition in the inheriting class header with the virtual keyword...

The rationale is that if you have code e.g.:

class A
{
  virtual void foo( void ) = 0;
}

class B : public A
{

  // if the user sees only this - they have no idea that
  // void foo( void ) is a virtual function...

  void foo( void ) { }; 
}

If class B is the API and class A is 'hidden' ( binary only - whatever ) and the user wanted to extend class B... then it isn't obvious to them that foo( ) function chain is virtualized... where as if class B declared virtual void foo( void ) it would be readily apparent....

Again - excluding it in your example won't hurt anything... but just thought I would point this out...



Oops... I forgot something... another item you might want to consider is to explicitly declare your destructor and make it virtual in you base class... if you don't and someone does e.g.:

player * p = new player_amarok( );

delete p;

If you do not do this and the derived class is simple - and by simply I mean e.g. no dynamically allocated memory - then you won't see any difference and all will be well... on the other hand if the derived class ( in the example player_amarok ) is using calls to new / etc. ... then the call to delete will only reference the BASE class destructor i.e. player::~player( ) and the derived class destructor will never be called... resulting in a slow and very hard to track memory leak... 

On the other hand - if your base class declares it's destructor virtual... then the call to delete will KNOW to call player_amarok::~player_amarok( ) followed by player::~player( )... etc.

Yes yes... most example code out there - even on some big ole technical sites - don't show this ( heck - my example above doesn't show it since its just supposed to be a 'code fragment' )... and SOME compilers will automatically generate a virtual destructor for you if they see virtual functions declared with no explicit definition of a destructor...

But trust me - its just as easy to explicitly declare it yourself so you KNOW what is going on and want to guarantee that proper behavior will occur... so its a GOOD THING... and you wouldn't believe how many times I have had things like this turn out to be the issue when people hire me to debug their code because they can't figure out where the memory leak(s) are...



Michael


"The only difference between me and a madman is that I'm not mad."

Salvador Dali (1904-1989)

Offline

  • Index
  • » C++
  • » Problems with pure virtual functions under gcc

Board footer

Powered by FluxBB