Problem using header files for the first time.

I know this has probably been asked 100 times but I can't find a thread which helps.

I'm using header files for the first time and the file is to initialise and define the classes I'm using. However, when I run the code I get the error "undefined reference to 'vtable...'".

As there are a lot of classes, I'll put the first one in to show what I'm doing.
In classes.h:
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
37
38
39
40
41
42
43
44
45
#ifndef CLASSES_H_INCLUDED
#define CLASSES_H_INCLUDED

//Initialise abstract base class for all shapes
class shapeBase{
public:
        //Initialise pure virtual functions
	//Translate shape
	virtual void Translate() = 0;
	//Rescale shape
	virtual void Rescale() = 0;
	//Rotate shape
	virtual void Rotate() = 0;
        //Print data
        virtual void Display() = 0;
	//Virtual destructor
	virtual ~shapeBase(){}
};

class isosTriangle: public shapeBase{
protected:
    //Define all variables this class will need
    double *Vertices;
    int numVertices;
public:
    //Constructor
    isosTriangle(double *Coords, int num): numVertices{num}{
        Vertices = new double[2*numVertices];
        for (int i{0};i<(2*numVertices);i++){
            Vertices[i] = Coords[i];
        }
    }
    //Destructor
    ~isosTriangle(){delete[] Vertices;}

    //Viewer - output a co-ordinate desired by the user
    void View(int i);
    void Translate();
    void Rescale();
    void Rotate();
    void Display();
    double xCentre(double *Coords);
    double yCentre(double *Coords);
};
#endif // CLASSES_H_INCLUDED 


As you can see, I'm using an abstract base class and inheriting from it and as far as I can see I'm redefining the pure virtual functions.
In classes.cpp:
1
2
3
4
5
6
7
8
9
10
#include...//Multiple includes here
#include "classes.h"
using namespace std;
void isosTriangle::View(int i) const {...}
void isosTriangle::Translate(){...}
void isosTriangle::Rescale(){...}
void isosTriangle::Rotate(){...}
void isosTriangle::Display(){...}
double isosTriangle::xCentre(double *Coords){...}
double isosTriangle::yCentre(double *Coords){...}


and finally, in main.cpp, the class is called to make a base class pointer
 
shapeBase *shape = new isosTriangle(arrayTemp, vert);


Any help would be really appreciated as I can't see what's wrong
Last edited on
If you just stick it all in a single file, like this, does it build?

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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
class shapeBase{
public:
        //Initialise pure virtual functions
	//Translate shape
	virtual void Translate() = 0;
	//Rescale shape
	virtual void Rescale() = 0;
	//Rotate shape
	virtual void Rotate() = 0;
        //Print data
        virtual void Display() = 0;
	//Virtual destructor
	virtual ~shapeBase(){}
};

class isosTriangle: public shapeBase{
protected:
    //Define all variables this class will need
    double *Vertices;
    int numVertices;
public:
    //Constructor
    isosTriangle(double *Coords, int num): numVertices{num}{
        Vertices = new double[2*numVertices];
        for (int i{0};i<(2*numVertices);i++){
            Vertices[i] = Coords[i];
        }
    }
    //Destructor
    ~isosTriangle(){delete[] Vertices;}

    //Viewer - output a co-ordinate desired by the user
    void View(int i) const;
    void Translate();
    void Rescale();
    void Rotate();
    void Display();
    double xCentre(double *Coords);
    double yCentre(double *Coords);
};


void isosTriangle::View(int i) const {}
void isosTriangle::Translate(){}
void isosTriangle::Rescale(){}
void isosTriangle::Rotate(){}
void isosTriangle::Display(){}
double isosTriangle::xCentre(double *Coords){}
double isosTriangle::yCentre(double *Coords){}

int main()
{
  double arrayTemp[10];
  int vert;
  shapeBase *shape = new isosTriangle(arrayTemp, vert);
}


If so, are you definitely linking with the object file formed by compiling classes.cpp ?
Last edited on
Yes, I originally built it in an individual file then separated it after it worked.
I believe I am linking the file cause I followed a guide on using header files but I honestly don't know.
Compiling classes.cpp throws the error "undefined reference to 'WinMain@16'". Not sure what that means either
What this all means is that you're not linking properly. If you're using an IDE, you probably need to put all these cpp files into the same "project" or whatever your IDE calls it, and build that project.
So it turns out, I think I've got it to work now but all the guides/tutorials I read are wrong.

In the guides they only said to do
1
2
#include "classes.h"
...

in both main.cpp and the other .cpp file.
I've just put in
1
2
3
#include "classes.h"
#include "classes.cpp"
...

and now it works,so go sort your guides out people :)

Thanks very much for helping, so annoying it was such an easy fix cause its been a problem for a few days now.
1
2
#include "classes.h"
#include "classes.cpp 


This is a very very bad idea. What you've done now is just put all the code into a single file, which is what you started with, but you've done it in a way that (while it works in this simple case) will go very very wrong if you tried it with a more complicated program.

Your problem is LINKING. You're not LINKING all the object files. Your solution has been to just copy and paste all the code back into a single file. This is a bad idea.
Last edited on
How do you link properly? I haven't seen anything about it before.
Last edited on
There are two aspects to it.

Firstly, if you're going to use multiple files, it's time to learn how C++ compiling and linking works. https://www.daniweb.com/programming/software-development/tutorials/466177/understanding-c-from-source-to-binaries

Secondly, if you're using an IDE, I expect it has "projects" and all the code needs to be in the same "project". If you're compiling at the command line, you just need to name each file.
I've read through that page but it's no clearer but I'll keep going while you respond.

I'm using codeblocks to write and run the code. As far as I'm aware it doesn't compile on the command line but all I know is that I press the 'build and run' button and it sorts all that out for me. Also, all the .cpp and .h files are in the same folder. Forgot to say, the output from my code goes to a console window rather than the command window.
Last edited on
Having all the cpp and h files in the same directory is a nice way for you to keep track but it's meaningless to the compiler and linker. They could be anywhere.

You need all these files in the same project.

http://wiki.codeblocks.org/index.php?title=Creating_a_new_project

Half-way down it talks about adding a pre-existing file.

Make a new project, add the files to it.
Finally, it's sorted and I'm only including the .h files.
So I was editing it slightly wrong and rather than opening the full project to edit I was just opening and editing the file directly so adding files didn't work. I've now opened it through the project and it works.

Thanks very much, that's brought a 3 day long problem to an end so it is really appreciated
Hi,

Just on your actual code:

Try to avoid raw pointers and new and delete. Instead make use of the STL containers as much as you can. They store their data on the heap and manage the memory themselves.

The trouble with new is the delete, if something happens (an exception is thrown) delete is never reached, so memory is leaked.

If you really need a pointer, as in a container of pointers for polymorphic behaviour, then consider smart pointers, either std::unique_ptr or std::shared_ptr. C++14 has std::make_unique and std::make_shared

http://en.cppreference.com/w/cpp/memory
http://en.cppreference.com/w/cpp/memory/unique_ptr/make_unique

Also, when you override a function, use the override keyword. http://en.cppreference.com/w/cpp/language/override

Edit:

Also avoid having protected or public member variables, make them private and provide interface functions to interact with them.
Last edited on
Topic archived. No new replies allowed.