I'm getting some errors when compiling my program. They relate to the constructor and destructor of my class Instruction.
Errors are:
/tmp/ccSWO7VW.o: In function `Instruction::Instruction(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, int)':
ale.c:(.text+0x241): undefined reference to `vtable for Instruction'
/tmp/ccSWO7VW.o: In function `Instruction::Instruction(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, int)':
ale.c:(.text+0x2ab): undefined reference to `vtable for Instruction'
/tmp/ccSWO7VW.o: In function `Instruction::~Instruction()':
ale.c:(.text+0x315): undefined reference to `vtable for Instruction'
/tmp/ccSWO7VW.o: In function `Instruction::~Instruction()':
ale.c:(.text+0x38d): undefined reference to `vtable for Instruction'
collect2: ld returned 1 exit status
Here is my code:
//classses.h
#include <iostream>
#include <string>
using namespace std;
class Instruction{
protected:
string name;
int value;
public:
Instruction(string _name, int _value);
~Instruction();
void setName(string _name);
void setValue(int _value);
string getName();
int getValue();
virtual void execute();
};
//constructor
Instruction::Instruction(string _name, int _value){
name = _name;
value = _value;
}
//destructor
Instruction::~Instruction(){
name = "";
value = 0;
}
void Instruction::setName(string _name){
name = _name;
}
void Instruction::setValue(int _value){
value = _value;
}
string Instruction::getName(){
return name;
}
int Instruction::getValue(){
return value;
}
/////////////////////////////////////////////////////////////////////
//ale.cpp
#include "headers.h"
#include "functions.h"
#include "classes.h"
#include <list>
using namespace std;
int main(){
return 0;
}
I would guess the problem is due to you declaring a virtual method 'execute' in the Instruction class, and never defining it anywhere. Compilers have to produce a vtable object for a class with virtual methods and really only want one copy of it, so they usually just do it in the compilation unit (source file) that defines the first virtual function...
You did not define your virtual function and/or g++ wants you to make your destructor virtual (because you have virtual functions which assumes inheritance)
Try
virtual void execute()=0;
This will make your class abstract, which seems to be what you intend since execute isn't defined.
If you ever want to use Instruction in more than one .cpp file, you should move the implementation of the class methods into a classes.cpp file.
As people already told, the problem is having execute() that is not implemented. Implement it, or make it pure virtual as says Dan Hook.
Just an extra remark: in many (maybe most depending on what you're coding on) cases, you don't need to implement the destructor. You just need if you want some specific functionnality (flushing data to a file for example).
As long as you have no pointer (as it is the case in your code), you won't have any memory tracking issues. Just remove the destructors: it's safe and it's less code.
However, if only one member is a pointer, then everything gets messy and you have to deal with memory management issues, memory leaks and segfaults ;)
Related
I'm reading the book "a complete guide to c++". I think there is a typo there on page 252. So I have three files as the following.
In file account.h,
// account.h
// Defining the class Account. class definition (methods prototypes) is usually put in the header file
// ---------------------------------------------------
#ifndef _ACCOUNT_ // if _ACCOUNT_ is not defined
#define _ACCOUNT_
#include <iostream>
#include <string>
using namespace std;
class Account
{
private:
string name;
unsigned long nr;
double balance;
public: //Public interface:
bool init( const string&, unsigned long, double);
void display();
};
#endif
// _ACCOUNT_
In file account.cpp,
// account.cpp
// Defines methods init() and display().
// ---------------------------------------------------
#include "account.h" // Class definition
#include <iostream>
#include <iomanip>
using namespace std;
// The method init() copies the given arguments
// into the private members of the class.
bool Account::init(const string& i_name,
unsigned long i_nr,
double i_balance)
{
if( i_name.size() < 1)
return false; // check data format to make sure it is valid
name = i_name;
nr = i_nr;
balance = i_balance;
return true;
}
// the method display() outputs private data.
void Account::display()
{
cout << fixed << setprecision(2)
<< "--------------------------------------\n"
<< "Account holder:" << name << '\n'
<< "Account number:" << nr << '\n'
<< "Account balance:" << balance << '\n'
<< "--------------------------------------\n"
<< endl;
}
And finally, in file account_t.cpp
// account_t.cpp
// Uses objects of class Account.
// ---------------------------------------------------
#include "account.h" // header file which contains class definition; (prototype for member functions)
int main()
{
Account current1, current2; // create two instances with name current1, current2
current1.init("Cheers, Mary", 1234567, -1200.99);
// have to call the init function to initialize a Account object; init function is public; members properties are private;
// that's why can not do current1.name = "nana" outside of the class definition
current1.display();
// current1.balance += 100; // Error: private member
current2 = current1;
current2.display();
current2.init("Jones, Tom", 3512347, 199.40);
current2.display();
Account& mtr = current1; // create a reference, which points to object current1
mtr.display();
return 0;
}
I do not think it's correct; because obviously there is no way to get access the init member methods and the display member methods, right? I hope this is not a naive question.
EDIT: I tried to run the main function in file account_t.cpp, and got the following output.
~$ g++ account_t.cpp
/tmp/ccSWLo5v.o: In function `main':
account_t.cpp:(.text+0x8c): undefined reference to `Account::init(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned long, double)'
account_t.cpp:(.text+0xb6): undefined reference to `Account::display()'
account_t.cpp:(.text+0xd5): undefined reference to `Account::display()'
account_t.cpp:(.text+0x132): undefined reference to `Account::init(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned long, double)'
account_t.cpp:(.text+0x15c): undefined reference to `Account::display()'
account_t.cpp:(.text+0x176): undefined reference to `Account::display()'
collect2: error: ld returned 1 exit status
Any more comments are greatly appreciated.
There is no issue with what you are asking about. init and display are declared public in the definition of class Account and the file with the class definition is #includeed properly in the .cpp using these methods.
In order to use a function only its declaration is needed (which is in the class definition in the header which is included). The definition/implementation in the .cpp file is not needed to use the function.
Each .cpp is compiled individually (called a translation unit) and afterwards each use of a function (for which only the declaration might have been available) is linked to the correct definitions from the other translation units if necessary via the function's scope, name and signature. This is called the linking process.
An introductory book to C++ should explain how compilation and linking process work.
For g++, there is an easy way to compile all .cpp files individually as translation units and then directly link them together:
g++ account_t.cpp account.cpp
You always need to add all .cpp to the compiler invocation like that. (There are alternative ways, but this is the easiest one.)
However, as mentioned in the comments there are other issues with this program:
_ACCOUNT_ is a reserved identifier that one may not #define in a program. All identifiers starting with an underscore followed by a capital letter are reserved. Using them causes undefined behavior.
using namespace std; is bad, at the very least when used in a header file, see Why is "using namespace std;" considered bad practice?.
Classes have constructors. One should not write init methods in most cases. The constructor is responsible for constructing and initializing class instances. But no constructor is used in the code.
Money should never be stored in double, because arithmetic with double is imprecise. You should store the value in an integer type in dimensions of the smallest relevant unit of money (e.g. cents).
#include <iostream> is not needed in the header file. One should avoid adding #includes that are not needed.
init returns a boolean indicating successful initialization. But main never checks that value. If a function can fail with an error value, then you must check that error value returned by the function to make sure that continuing the rest of the program is safe.
Some of these points may be excusable as simplification for a beginner program, depending on how far the book got at this point (though 200+ pages should already cover a lot), but others aren't.
Example of constructor use doing the same thing:
class Account
{
private:
string name;
unsigned long nr;
double balance;
public: //Public interface:
Account(const string&, unsigned long, double);
void display();
};
Account::Account(const string& i_name,
unsigned long i_nr,
double i_balance)
: name(i_name), nr(i_nr), balance(i_balance)
{
}
int main()
{
Account current1("Cheers, Mary", 1234567, -1200.99);
// Create Account instance and initialize private members; constructor is public; members properties are private;
// that's why can not do current1.name = "nana" outside of the class definition
current1.display();
// current1.balance += 100; // Error: private member
Account current2 = current1; // Create second Account instance and copy private members from first one
current2.display();
current2 = Account("Jones, Tom", 3512347, 199.40); // Replace instance with a copy of a new one
current2.display();
Account& mtr = current1; // create a reference, which points to object current1
mtr.display();
return 0;
}
The i_name.size() < 1 check (which is weirdly written, why not i_name.size() == 0?) would be realized by throwing an exception from the constructor:
Account::Account(const string& i_name,
unsigned long i_nr,
double i_balance)
: name(i_name), nr(i_nr), balance(i_balance)
{
if(i_name.size() == 0) {
throw invalid_argument("Account does not accept empty names!");
}
}
This requires #include<stdexcept> and is a more advanced topic.
Here's my code:
menuState.hpp
#ifndef MENU_STATE_HPP
#define MENU_STATE_HPP
#include "state.hpp"
#include <SFML/Graphics.hpp>
class MenuState : public State
{
public:
MenuState();
static void create(StateListener* Parent, const std::string name)
{
MenuState* myState = new MenuState();
myState->parent = Parent;
Parent->manageState(name, myState);
}
void enter();
void exit();
void resume();
private:
};
#endif // MENU_STATE_HPP
I'm getting an undefined reference to the constructor when I do MenuState* myState = new MenuState(); and I'm not sure why because MenuState::MenuState() comes before the create function in the class declaration.
EDIT: I'm also getting the same error to all my sfml functions.
Here's the exact build messages: http://pastebin.com/e819FhPj
I do have the sfml libraries linked and the header path set in my compilers search directories.
It is always best to show the exact text of the error, but my educated guess is, you are getting a linker error, not a compiler error. Have you actually implemented the constructor anywhere? I bet you haven't.
I'm not an experience C++ developer but it seems like MenuState constructor is declared but not defined.
Replace MenuState(); with MenuState(){} should fix the error.
I've been searching for a while and have found a lot of threads/pages that involve the problem I have, but I am not able to find
An explanation of why this error occurs
A working solution for my specific case
The following is Scanner.h:
class BaseReader {
public:
virtual ~BaseReader();
virtual const char* read() = 0;
virtual long position() = 0;
virtual long size() = 0;
virtual void seek(long position) = 0;
};
class CharReader : public BaseReader {
public:
CharReader(const char* source);
CharReader(const char* source, long size);
~CharReader();
const char* read();
long position();
long size();
void seek(long position);
private:
char* _source;
long _position;
long _size;
};
In Scanner.cpp I simply implement one of the constructors of CharReader.
I use Code::Blocks, but compiling it by myself results in the exact same problem.
niklas#emerald:~/git/hiterator (CPP)$ g++ main.cpp hiterator/Scanner.cpp -o main
/tmp/cclNNwgl.o: In function `hiterator::CharReader::CharReader(char const*)':
Scanner.cpp:(.text+0x16): undefined reference to `vtable for hiterator::CharReader'
collect2: ld gab 1 als Ende-Status zurück
#qdii:
#include "Scanner.h"
using namespace hiterator;
#include <stdlib.h>
#include <string.h>
CharReader::CharReader(const char* source) {
_size = strlen(source);
_source = (char*) malloc(_size + 1);
memcpy(_source, source, _size + 1);
}
Your program is incorrect. All virtual functions are considered used (odr-used) and thus you need to provide the definitions for all of them. Once you fix that, the issue should go away.
The compiler is complaining that the vtable is not available. Vtable-s are an implementation detail, and thus not treated by the standard, but many compilers will generate the vtable in the translation unit that defines the first (non-inline) virtual function. In your case, whatever the criterion to generate the vtable is, you are not complying with it.
See what I wrote on the GCC wiki to explain undefined reference to vtable for X errors.
There are also loads of existing questions on SO about that linker error, I'm sure one of them has an answer that explains it, e.g. here or here
You declared, but didn’t define, the virtual destructor in BaseReader. You need to provide a definition for this in the .cpp file in order for the vtable for BaseReader to be generated. Same for CharReader.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
GCC C++ Linker errors: Undefined reference to 'vtable for XXX', Undefined reference to 'ClassName::ClassName()'
I'm doing a little project in C++ and I've come into some problems regarding virtual functions.
I have a base class with some virtual functions:
#ifndef COLLISIONSHAPE_H_
#define COLLISIONSHAPE_H_
namespace domino
{
class CollisionShape : public DominoItem
{
public:
// CONSTRUCTOR
//-------------------------------------------------
// SETTERS
//-------------------------------------------------
// GETTERS
//-------------------------------------------------
virtual void GetRadius() = 0;
virtual void GetPosition() = 0;
virtual void GetGrowth(CollisionShape* other) = 0;
virtual void GetSceneNode();
// OTHER
//-------------------------------------------------
virtual bool overlaps(CollisionShape* shape) = 0;
};
}
#endif /* COLLISIONSHAPE_H_ */
and a SphereShape class which extends CollisionShape and implements the methods above
/* SphereShape.h */
#ifndef SPHERESHAPE_H_
#define SPHERESHAPE_H_
#include "CollisionShape.h"
namespace domino
{
class SphereShape : public CollisionShape
{
public:
// CONSTRUCTOR
//-------------------------------------------------
SphereShape();
SphereShape(CollisionShape* shape1, CollisionShape* shape2);
// DESTRUCTOR
//-------------------------------------------------
~SphereShape();
// SETTERS
//-------------------------------------------------
void SetPosition();
void SetRadius();
// GETTERS
//-------------------------------------------------
void GetRadius();
void GetPosition();
void GetSceneNode();
void GetGrowth(CollisionShape* other);
// OTHER
//-------------------------------------------------
bool overlaps(CollisionShape* shape);
};
}
#endif /* SPHERESHAPE_H_ */
and the .cpp file:
/*SphereShape.cpp*/
#include "SphereShape.h"
#define max(a,b) (a>b?a:b)
namespace domino
{
// CONSTRUCTOR
//-------------------------------------------------
SphereShape::SphereShape(CollisionShape* shape1, CollisionShape* shape2)
{
}
// DESTRUCTOR
//-------------------------------------------------
SphereShape::~SphereShape()
{
}
// SETTERS
//-------------------------------------------------
void SphereShape::SetPosition()
{
}
void SphereShape::SetRadius()
{
}
// GETTERS
//-------------------------------------------------
void SphereShape::GetRadius()
{
}
void SphereShape::GetPosition()
{
}
void SphereShape::GetSceneNode()
{
}
void SphereShape::GetGrowth(CollisionShape* other)
{
}
// OTHER
//-------------------------------------------------
bool SphereShape::overlaps(CollisionShape* shape)
{
return true;
}
}
These classes, along some other get compiled into a shared library.
Building libdomino.so
g++ -m32 -lpthread -ldl -L/usr/X11R6/lib -lglut -lGLU -lGL -shared -lSDKUtil -lglut -lGLEW -lOpenCL -L/home/adrian/AMD-APP-SDK-v2.4-lnx32/lib/x86 -L/home/adrian/AMD-APP-SDK-v2.4-lnx32/TempSDKUtil/lib/x86 -L"/home/adrian/AMD-APP-SDK-v2.4-lnx32/lib/x86" -lSDKUtil -lglut -lGLEW -lOpenCL -o build/debug/x86/libdomino.so build/debug/x86//Material.o build/debug/x86//Body.o build/debug/x86//SphereShape.o build/debug/x86//World.o build/debug/x86//Engine.o build/debug/x86//BVHNode.o
When I compile the code that uses this library I get the following error:
../../../lib/x86//libdomino.so: undefined reference to `vtable for domino::CollisionShape'
../../../lib/x86//libdomino.so: undefined reference to `typeinfo for domino::CollisionShape'
Command used to compile the demo that uses the library:
g++ -o build/debug/x86/startdemo build/debug/x86//CMesh.o build/debug/x86//CSceneNode.o build/debug/x86//OFF.o build/debug/x86//Light.o build/debug/x86//main.o build/debug/x86//Camera.o -m32 -lpthread -ldl -L/usr/X11R6/lib -lglut -lGLU -lGL -lSDKUtil -lglut -lGLEW -ldomino -lSDKUtil -lOpenCL -L/home/adrian/AMD-APP-SDK-v2.4-lnx32/lib/x86 -L/home/adrian/AMD-APP-SDK-v2.4-lnx32/TempSDKUtil/lib/x86 -L../../../lib/x86/ -L"/home/adrian/AMD-APP-SDK-v2.4-lnx32/lib/x86"
(the -ldomino flag)
And when I run the demo, I manually tell it about the library:
LD_LIBRARY_PATH=../../lib/x86/:$AMDAPPSDKROOT/lib/x86:$LD_LIBRARY_PATH bin/x86/startdemo
After reading a bit about virtual functions and virtual tables I understood that virtual tables are handled by the compiler and I shouldn't worry about it, so I'm a little bit confused on how to handle this issue.
I'm using gcc version 4.6.0 20110530 (Red Hat 4.6.0-9) (GCC)
Later edit:
I'm really sorry, but I wrote the code by hand directly here.
I have defined the return types in the code.
I apologize to the 2 people that answered below.
I have to mention that I am a beginner at using more complex project layouts in C++.By this I mean more complex makefiles, shared libraries, stuff like that.
My problem was caused by the fact that I didn't define the body of virtual void CollisionShape::GetSceneNode().
The way to fix this is to either define the above function, or declare it as pure virtual as such:
virtual void CollisionShape::GetSceneNode() = 0;
Any non-pure virtual function must be defined, even if it's never used. A missing definition will often result in the 'vtable undefined' linker error, especially when the very first non-pure, non-inline virtual function of a class is left undefined. In your case, CollisionShape::GetSceneNode() is left undefined.
On an unrelated note, every class that has a virtual function needs a virtual destructor, every time, absolutely no exceptions whatsoever. The language unfortunately doesn't enforce this, so it's your responsibility. G++ has a flag, -Weffc++, which enables warnings for this and other common pitfalls, described in the Scott Meyers's book "Effective C++". I strongly recommend using this flag all the time. Using -Werror by default is also a good habit. Suppress individual warnings one by one, and only if there's no possibility to fix the code.
I can't say for certain whether this will fix your compilation error, but in any case you need to declare a virtual destructor (virtual ~CollisionShape()) in your CollisionShape class. Failure to do so will result in undefined runtime behavior when SphereShape is deleted through its base class pointer (a pointer to CollisionShape). Of course, since a virtual constructor is indeed added to a class's vtbl, I guess it's not beyond the realm of possibility that this is the culprit behind your error.
In Effective C++, Scott Meyers has the following to say.
The C++ language standard is unusually clear on this topic. When you try to delete a derived class object through a base class pointer and the base class has a nonvirtual destructor [...], the results are undefined. That means compilers may generate code to do whatever they like: reformat your disk, send suggestive mail to your boss, fax source code to your competitors, whatever. (What often happens at runtimme is that the derived class's destructor is never called. [...])
Due to the conflicting declarations of GetSceneNode, in your current code
virtual void GetSceneNode();
in the base class, and
SceneNode* GetSceneNode();
in the derived class, your code should not compile. You should not get to the linking stage. I'm pretty sure that the code that you're presenting is not your real code.
Hence, I downvoted the question.
But regarding the error that you evidently produced with some other code, it has been asked before on SO, and answered for example here.
Hence, I also voted to close the question.
Cheers & hth.,
This may not be the whole problem, but you are missing a return type on those functions. ie
virtual double GetPosition() = 0;
gsoap with its tools wsdl2h and soapcpp2 provided me with a soapStub.h file containing the following:
class SOAP_CMAC ns2__SOAPKunden
{
public:
std::string *adresszusatz;
// ...
public:
virtual int soap_type() const { return 7; }
// ...
ns2__SOAPKunden() : adresszusatz(NULL), x(NULL) { } // left out all member init.
virtual ~ns2__SOAPKunden() { }
};
I start with a small app using the class to populate objects with data from informix DB.
But to compile successfully i have to leave away all the virtual stuff - i found many postings about this error and use of virtual members in subclasses - otherwise i get
main.o: In function `ns2__SOAPKunden::ns2__SOAPKunden()':
main.cpp:(.text._ZN15ns2__SOAPKundenC1Ev[ns2__SOAPKunden::ns2__SOAPKunden()]+0xf): undefined reference to `vtable for ns2__SOAPKunden'
main.o: In function `ns2__SOAPKunden::~ns2__SOAPKunden()':
main.cpp:(.text._ZN15ns2__SOAPKundenD1Ev[ns2__SOAPKunden::~ns2__SOAPKunden()]+0x13): undefined reference to `vtable for ns2__SOAPKunden'
collect2: ld returned 1 exit status
I admit after years of scripting only it's very hard for me to make sense of C++ code... I want to ask for any advice what to try next. My class is no derived class, is for example what makes me wonder.
The error means that the virtual table has not been correctly compiled/linked in the final binary (executable or library). There are two common circumstances that lead to this error:
you are not linking the object file that includes the virtual table definitions --i.e. you compiled soapStub.cpp into soapStub.o, but did not add that binary to the linker command line.
the compiler is not generating the virtual table anywhere, so even if you are including all object files, that does not include the virtual table.
The second case is the hardest to identify for non-experienced developers, and can be caused by a class that is defined in the header and contains virtual functions. If all the virtual functions are defined inlined, the compiler will generate the virtual table in all translation units that include the header, and mark it as a weak symbol so that the linker can discard them, but if you later add a new virtual method and you leave it undefined in the header --or if you remove the definition from one of the virtual functions--, then the compiler will not generate the virtual table in each translation unit, but only in the one that defines those functions.
Things to check:
you are linking all object files
either all virtual functions are defined inline in the class definition or you have a .cpp that defines the virtual functions and you are linking that in.
This is what David Rodriguez said, just stated simpler I guess...
I had this situation in my interface class:
class IBase
{
public:
virtual void begin(unsigned long);
virtual void end();
virtual int available(void) = 0;
virtual int peek(void) = 0;
virtual int read(void) = 0;
virtual void flush(void) = 0;
}
and changed it to this:
class IBase
{
public:
virtual void begin(unsigned long) = 0;
virtual void end() = 0;
virtual int available(void) = 0;
virtual int peek(void) = 0;
virtual int read(void) = 0;
virtual void flush(void) = 0;
}
which did the trick.
begin() and end() were defined in derived class in a different file, IBase class (interface) was only declared in header and included in few places.
Error from OP only appeared when I set optimizations to none (-O0), any other setting resulted in no error (gcc 4.8).