Trouble with c++ virtual functions

Started by
3 comments, last by Emmanuel Deloget 17 years, 4 months ago
I've been playing with this one for quite a while, arguing with it, setting up mockups and demos, etc. Would you please help me? Here's the compiler output:


Compiler: Default compiler
Building Makefile: "C:\Documents and Settings\Owner\Desktop\clank\Makefile.win"
Finding dependencies for file: C:\Documents and Settings\Owner\Desktop\clank\clank.cpp
Finding dependencies for file: C:\Documents and Settings\Owner\Desktop\clank\graphics.cpp
Finding dependencies for file: C:\Documents and Settings\Owner\Desktop\clank\module.cpp
Finding dependencies for file: C:\Documents and Settings\Owner\Desktop\clank\spacething.cpp
Finding dependencies for file: C:\Documents and Settings\Owner\Desktop\clank\input.cpp
Finding dependencies for file: C:\Documents and Settings\Owner\Desktop\clank\script.cpp
Finding dependencies for file: C:\Documents and Settings\Owner\Desktop\clank\vector.cpp
Finding dependencies for file: C:\Documents and Settings\Owner\Desktop\clank\world.cpp
Finding dependencies for file: C:\Documents and Settings\Owner\Desktop\clank\frobnitz.cpp
Finding dependencies for file: C:\Documents and Settings\Owner\Desktop\clank\defineable.cpp
Finding dependencies for file: C:\Documents and Settings\Owner\Desktop\clank\ntime.cpp
Executing  make...
make.exe -f "C:\Documents and Settings\Owner\Desktop\clank\Makefile.win" all
g++.exe -D__DEBUG__ -c clank.cpp -o clank.o -I"C:/Dev-Cpp/lib/gcc/mingw32/3.4.2/include"  -I"C:/Dev-Cpp/include/c++/3.4.2/backward"  -I"C:/Dev-Cpp/include/c++/3.4.2/mingw32"  -I"C:/Dev-Cpp/include/c++/3.4.2"  -I"C:/Dev-Cpp/include"  -I"C:/clank/include"    -pg -g3

g++.exe -D__DEBUG__ -c module.cpp -o module.o -I"C:/Dev-Cpp/lib/gcc/mingw32/3.4.2/include"  -I"C:/Dev-Cpp/include/c++/3.4.2/backward"  -I"C:/Dev-Cpp/include/c++/3.4.2/mingw32"  -I"C:/Dev-Cpp/include/c++/3.4.2"  -I"C:/Dev-Cpp/include"  -I"C:/clank/include"    -pg -g3

g++.exe -D__DEBUG__ -c script.cpp -o script.o -I"C:/Dev-Cpp/lib/gcc/mingw32/3.4.2/include"  -I"C:/Dev-Cpp/include/c++/3.4.2/backward"  -I"C:/Dev-Cpp/include/c++/3.4.2/mingw32"  -I"C:/Dev-Cpp/include/c++/3.4.2"  -I"C:/Dev-Cpp/include"  -I"C:/clank/include"    -pg -g3

g++.exe -D__DEBUG__ clank.o graphics.o module.o spacething.o input.o script.o vector.o world.o frobnitz.o defineable.o ntime.o clank_private.res -o "clank.exe" -L"C:/Dev-Cpp/lib" -L"C:/clank/lib"  -lgmon -pg  -g3 

module.o(.text+0xe09): In function `ZN6moduleC2Ev':
C:/Documents and Settings/Owner/Desktop/clank/module.cpp:74: undefined reference to `vtable for module'
module.o(.text+0xf77): In function `ZN6moduleC1Ev':
C:/Documents and Settings/Owner/Desktop/clank/module.cpp:74: undefined reference to `vtable for module'
module.o(.text+0x1142): In function `ZN6moduleC2EN5boost10shared_ptrI5worldEE':
C:/Documents and Settings/Owner/Desktop/clank/module.cpp:80: undefined reference to `vtable for module'
module.o(.text+0x1318): In function `ZN6moduleC1EN5boost10shared_ptrI5worldEE':
C:/Documents and Settings/Owner/Desktop/clank/module.cpp:80: undefined reference to `vtable for module'
module.o(.text+0x147c): In function `ZN6moduleD2Ev':
C:/Documents and Settings/Owner/Desktop/clank/module.cpp:87: undefined reference to `vtable for module'
module.o(.text+0x15da):C:/Documents and Settings/Owner/Desktop/clank/module.cpp:87: more undefined references to `vtable for module' follow
module.o(.text+0x174a): In function `ZN12constructionC2Ev':
C:/Documents and Settings/Owner/Desktop/clank/module.cpp:103: undefined reference to `vtable for construction'
module.o(.text+0x184c): In function `ZN12constructionC1Ev':
C:/Documents and Settings/Owner/Desktop/clank/module.cpp:103: undefined reference to `vtable for construction'
module.o(.text+0x19ab): In function `ZN12constructionC2EN5boost10shared_ptrI5worldEE':
C:/Documents and Settings/Owner/Desktop/clank/module.cpp:107: undefined reference to `vtable for construction'
module.o(.text+0x1b17): In function `ZN12constructionC1EN5boost10shared_ptrI5worldEE':
C:/Documents and Settings/Owner/Desktop/clank/module.cpp:107: undefined reference to `vtable for construction'
module.o(.text+0x1c4a): In function `ZN12constructionD2Ev':
C:/Documents and Settings/Owner/Desktop/clank/module.cpp:123: undefined reference to `vtable for construction'
module.o(.text+0x1d50):C:/Documents and Settings/Owner/Desktop/clank/module.cpp:123: more undefined references to `vtable for construction' follow
collect2: ld returned 1 exit status

make.exe: *** [clank.exe] Error 1

Execution terminated


Here's the definition. It was working perfectly, and the only thing I changed was adding the virtual keyword, in class module. ignore the random musings interspersed with the code. i tend to type whatever I'm thinking, to help myself think.

#ifndef MODULE_H
#define MODULE_H


#include <boost/shared_ptr.hpp>
#include <string>
#include <list>
#include "spacething.h"
#include "frobnitz.h"
#include "graphics.h"
#include "world.h"

#define C_DATA      0
#define C_STRUCTURE 1
#define C_RESOURCE  2

class ship;
class module;
class prototype;



/*Design ponding: WHat does a prototype do that a mdule does not? 
Well, for one thing, it completes, and creates another module after some set 
time. It also does not require an action, except perhaps to influence the speed
of construction, but I can't see why you would want to do that.  The only thing 
is that itneeds to instantiate a particular module at  a given time, and that 
can be done on hte update()
Answer: it posses a prototype, and a modifier for that prototype!  It also has a
*/

class prototype
{
    private:
    resource resourceCost;
    integrity Integrity;
    int timeCost;
    public:
    prototype();
    resource getResourceCost();
    resource setResourceCost(const resource &);
    integrity getIntegrity();
    integrity setIntegrity(const integrity &);
    int getTimeCost();
    int setTimeCost(const int & );
};

class connection : public spacething
{
    private:
    boost::shared_ptr<spacething> a;
    boost::shared_ptr<spacething> b;
    int connection_type;
    public:
    connection();
    connection(boost::shared_ptr<spacething> A, boost::shared_ptr<spacething> B);
    ~connection();
    /*note: it should never matter which one is module a and which is module b*/
};

class protoconnection : public prototype
{
    private:
    float yield;
    float decayfactor;
    public:
};

class module : public spacething
{
    private:
    //game logic
    resource cargo;
    boost::shared_ptr<ship> owner;
    
    public:
    module();
    module(boost::shared_ptr<world>);
    ~module();
    virtual void update();
    void act(frobnitz details);
};

class construction : public module //this module will be used later, after
{
    private:
    boost::shared_ptr<prototype> archetype;
    frobnitz adjustments;
    int timeOfCompletion;/*not updated: this is the date, relative to the start
            of the program, in milliseconds that the module will be created.*/
    public:
    construction();
    construction(boost::shared_ptr<world>);
    float getCompletion();
    void update();
    void act(frobnitz details);
    ~construction();
};

class engine : public module
{
    private:
    float power;
    float decayfactor;
    
    public:
    engine();
    engine(boost::shared_ptr<world>);
    ~engine();
    void update();
    void act(frobnitz details);   
};

class protoengine : public prototype
{
    float power;
    float decayfactor;
};

class ship      /*ships have no use, as yet. They exist so that modules can be grouped.*/
{
    private:
    std::list<boost::shared_ptr<module> > parts;
    public:
    //interactions with module
    void add(boost::shared_ptr<module> m);
    int remove(boost::shared_ptr<module> m);
};

#endif /*MODULE_H*/



/*Notes on prototypes and modules and construction
 * Prototypes are meant ot be archetypal forms of modules. They represent a 
 * particular technology, and the archetypal form of this technology. We are 
 * considering adding a variable, so the player can choose to build, for
 * example, a particular model of engine on a different scale than the original.
  
 * Prototypes exist so that a script can describe a particular type of module
 * just once, and ever after eb able to refer to that prototype to instantiate a
 * module from. a construction object will have a pointer to a prototype, and 
 * when the construction finishes, a module will be created. It's spacething 
 * data will be copied from the construction, and the particulars of the module
 * will be generated from the prototype. 
 
 * If a prototype represents a particular technology, it may be possible to 
 * create a module similar to the base technology, but slightly modified. 
 * for example: an engine built on a scale larger than the original. 
 * 
 * It is hoped that a single class may be created, both for adjusting 
 * prototypes, and for sending arguments to module::frobnicate.
 
 * under normal circumstances, a module should be instantiated from a prototype.
 * for every class, <module type>, derived from module, a class should be
 * derived from prototype, with the form proto<module type>. thus, if a class,
 * weapon, were derived from module, a class would also have to be derived from 
 * prototype: protoweapon. if a class were then derived from weapon, coilgun, 
 * then a class called protocoilgun would have to be derived from protoweapon.
 */
 /*Sequence For construction of a module
    a Construction module will be given an order.  TO do this, a non-colliding 
    construction object will be created by the user interface, and a 
    non-colliding connection may be created to hold it in place, untill it 
    becomes colliding. The construction module will be passed a frobnitz 
    containing the construction object, again, by the user interface. THe 
    Construction module, if it within range, will commence construction, at
    which point the construction object will become corporeal, along with any
    subordinate constructions, such as connections holding it in place. as these
    connections become collidable, they go from infinite(non-corporeal) 
    integrity to almost zero integrity, which may cause them to break if the
    ship is under acceleration. To counteract this, the construction module will
    use a clamp to form a relatively strong connection with the module, holding
    it relative to the construction module.
 */

Advertisement
Have you actually given module::update a body?
I don't have a lot of experience with g++, but you might try adding the stdc++ library to the linker (-lstdc++).
I checked, and lo and behold, In my infinite wisdom, I had neglected that. Thank Sneftel. You're the best.

However, that didn't quite do it. The body, along with the compiler output is below.
make.exe -f "C:\Documents and Settings\Owner\Desktop\clank\Makefile.win" allg++.exe -D__DEBUG__ -c module.cpp -o module.o -I"C:/Dev-Cpp/lib/gcc/mingw32/3.4.2/include"  -I"C:/Dev-Cpp/include/c++/3.4.2/backward"  -I"C:/Dev-Cpp/include/c++/3.4.2/mingw32"  -I"C:/Dev-Cpp/include/c++/3.4.2"  -I"C:/Dev-Cpp/include"  -I"C:/clank/include"    -pg -g3g++.exe -D__DEBUG__ clank.o graphics.o module.o spacething.o input.o script.o vector.o world.o frobnitz.o defineable.o ntime.o clank_private.res -o "clank.exe" -L"C:/Dev-Cpp/lib" -L"C:/clank/lib"  -lgmon -pg  -g3 module.o(.text+0x176a): In function `ZN12constructionC2Ev':C:/Documents and Settings/Owner/Desktop/clank/module.cpp:111: undefined reference to `vtable for construction'module.o(.text+0x186c): In function `ZN12constructionC1Ev':C:/Documents and Settings/Owner/Desktop/clank/module.cpp:111: undefined reference to `vtable for construction'module.o(.text+0x19cb): In function `ZN12constructionC2EN5boost10shared_ptrI5worldEE':C:/Documents and Settings/Owner/Desktop/clank/module.cpp:115: undefined reference to `vtable for construction'module.o(.text+0x1b37): In function `ZN12constructionC1EN5boost10shared_ptrI5worldEE':C:/Documents and Settings/Owner/Desktop/clank/module.cpp:115: undefined reference to `vtable for construction'module.o(.text+0x1c6a): In function `ZN12constructionD2Ev':C:/Documents and Settings/Owner/Desktop/clank/module.cpp:131: undefined reference to `vtable for construction'module.o(.text+0x1d70):C:/Documents and Settings/Owner/Desktop/clank/module.cpp:131: more undefined references to `vtable for construction' followcollect2: ld returned 1 exit statusmake.exe: *** [clank.exe] Error 1Execution terminated


The body of the function in question, excerpted from the cpp file, is empty for now.

void module::update(){    }


Would you mind teaching me a little about the meaning of the linker output? Or send me to a tutorial. I want to understand it. I find it considerably less intuitive than compiler errors..
Because since construction inherit module and since module::update() is virtual, construction::update() is also virtual and also need to be defined (because there's a hidden reference to it in the construction clmass virtual function table (vtable)).

Regards,

This topic is closed to new replies.

Advertisement