Undefined reference to vtable for Compte - c++

I'm trying to build a C++ project for a course I'm following and I'm having a lot of troubles.
I have this header:
#ifndef COMPTE_H_
#define COMPTE_H_
#include <string>
class Compte {
public:
Compte (unsigned int p_noCompte, double p_tauxInteret, double p_solde,const std::string& p_description);
virtual ~Compte (){} ;
void asgSolde (const double p_solde);
unsigned int reqNoCompte () const;
double reqTauxInteret () const;
double reqSolde () const;
std::string reqDescription () const;
std::string reqCompteFormate() const;
virtual Compte* clone() const;
virtual const double calculerInteret();
private:
unsigned int m_noCompte;
double m_tauxInteret;
double m_solde;
std::string m_description;
};
#endif /* COMPTE_H_ */
And the corresponding cpp file:
#include "Compte.h"
#include <string>
#include <sstream>
using namespace std;
Compte::Compte (unsigned int p_noCompte, double p_tauxInteret, double p_solde, const string& p_description)
: m_noCompte(p_noCompte), m_tauxInteret(p_tauxInteret), m_solde(p_solde), m_description(p_description)
{
}
void Compte::asgSolde (const double p_solde)
{
m_solde = p_solde;
}
unsigned int Compte::reqNoCompte () const{
return m_noCompte;
}
double Compte::reqTauxInteret() const{
return m_tauxInteret;
}
double Compte::reqSolde() const{
return m_solde;
}
string Compte::reqDescription() const{
return m_description;
}
string Compte::reqCompteFormate()const
{
ostringstream compteFormate;
return compteFormate.str();
}
However I have the following errors popping:
Description Resource Path Location Type
undefined reference to « vtable for Compte » Compte.cpp /Travail Pratique 2 line 14 C/C++ Problem
For the constructor in the .cpp file,
Description Resource Path Location Type
undefined reference to « vtable for Compte » Compte.cpp /Travail Pratique 2 line 14 C/C++ Problem
For the class Compte{ line in the .header file, and lastly
Description Resource Path Location Type
undefined reference to « vtable for Compte » Compte.h /Travail Pratique 2 line 16 C/C++ Problem
For the virtual ~Compte(){}; line.
What's wrong with my code, how can I correct this?

You forgot to implement 2 virtual methods, the clone and the calculerInteret.
That is why your linker is complaining. Your linker is not complaining about the destructor but he has trouble creating the virtual method table because 2 methods that are marked virtual, are missing.
Only a linker can find issues like that because in theory these methods can even be spread over multiple source files.
If it is your intent to create abstract methods do this :
virtual Compte* clone() const=0;
virtual const double calculerInteret()=0;
of course you realise you cannot instantiate classes that have abstract methods right ?

Not the problem in this case but may be the problem for anyone viewing this post:
Forgetting a body on a virtual destructor generates the following:
undefined reference to `vtable for CYourClass'.
I am adding a note because the error message is deceptive. (This was with gcc version 4.6.3.)
So add:
Compte::~Compte()
{
}
To your cpp file.
EDIT 1: As pointed out by Philip Stuyck: If the destructor were missing , then you would have had a similar error, but you can have it for any missing virtual method. If the virtual is inline yes or no does not matter, you just need one if its virtual.

Related

how to properly include .h, and .tpp

I have the following project structure:
This a handler for the "IOPin" class:
//IOPinHandler class
//IOPinHandler.h
#include <type_traits>
class IOPin; //forward declaration required
class IOPinHandler
{
public:
explicit IOPinHandler() { }
virtual ~IOPinHandler() { }
void checkBool(const bool& b);
void checkInt(const int& b);
template<typename T>
void modifyIOPinMember(IOPin& ioPin, const T& param);
};
//To avoid multiple definitions
#ifndef _OD_
void IOPinHandler::checkBool(const bool& b)
{
//Do stuff
}
void IOPinHandler::checkInt(const int& b)
{
//Do stuff
}
#endif
The following is the .tpp file for the definition of modifyIOPinMember member.
//IOPinHandler class
//IOPinHandler.tpp
template<typename T>
void IOPinHandler::modifyIOPinMember(IOPin& ioPin, const T& param)
{
if constexpr(std::is_same_v<T, int>)
{
checkInt(param);
ioPin.m2 = param;
}
else if constexpr(std::is_same_v<T, bool>)
{
checkBool(param);
ioPin.m1 = param;
}
}
The following is the "IOPin" class, the one meant to be handled by the class above. Since IOPinHandler's modifyIOPinMember member requires to know the definition of "IOPin" (its complete type) then, the IOPinHandler.tpp file is included in IOPin.h file as follows:
//IOPin class
//IOPin.h
//To avoid multiple definitions
#define _OD_
#include "IOPinHandler.h"
class IOPin
{
public:
explicit IOPin(const bool& b, const int& n):m1(b), m2(n) { _handler = new IOPinHandler; }
void setInt(const int& n) { _handler->modifyIOPinMember(*this, n); }
void setBool(const bool& b) { _handler->modifyIOPinMember(*this, b); }
private:
bool m1{false};
int m2{0};
IOPinHandler* _handler{nullptr};
friend class IOPinHandler;
};
#include "IOPinHandler.tpp"
The problem is that calling either setInt or SetBool methods, result in a compile time error:
//main.cpp
#include "IOPin.h"
IOPin a(false, 0);
int main()
{
a.setInt(89);
a.setBool(true);
return 0;
}
This is the error:
/usr/bin/ld: /tmp/ccpKv7HW.o: in function `void IOPinHandler::modifyIOPinMember<int>(IOPin&, int const&)':
main.cpp:(.text._ZN12IOPinHandler17modifyIOPinMemberIiEEvR5IOPinRKT_[_ZN12IOPinHandler17modifyIOPinMemberIiEEvR5IOPinRKT_]+0x27): undefined reference to `IOPinHandler::checkInt(int const&)'
/usr/bin/ld: /tmp/ccpKv7HW.o: in function `void IOPinHandler::modifyIOPinMember<bool>(IOPin&, bool const&)':
main.cpp:(.text._ZN12IOPinHandler17modifyIOPinMemberIbEEvR5IOPinRKT_[_ZN12IOPinHandler17modifyIOPinMemberIbEEvR5IOPinRKT_]+0x27): undefined reference to `IOPinHandler::checkBool(bool const&)'
collect2: error: ld returned 1 exit status
What am I missing over here?
I know that a solution is to create a "IOPinHandler.cpp" file and put there the definitions for "checkBool" and "checkInt" methods, however I dont want to have a separate .cpp file only for that.
Thanks in advance.
In C++, we almost never include the implementation file, only header (.h) files; and, if your class is templated, all class's function implementations should be in header only; no secondary file is needed or advised, and you should always use header guards for your header files, used as follows:
#ifndef ANY_UNIQUE_NAME // recommended related to header file name
#define ANY_UNIQUE_NAME
//#includes <...>
//header code
#endif
Then you include headers when you need them.

What causes the error #18 expected a ")" on a MSP430

Compiling the following C++14 code for a MSP430 using TI Code Composer I got the following errors:
subdir_rules.mk:14: recipe for target 'main.obj' failed
"Interface.h", line 75: error #18: expected a ")"
"Derived.h", line 91: error #18: expected a ")"
This is for the following code structure in which the Interface.h class is a library which compiles fine for STM32 targets.
#include <cstdint>
namespace NS
{
class Interface
{
public:
// Other pure virtual functions such as:
virtual void advance() = 0;
// This is the problem function
virtual void advance(const uint32_t N) = 0;
};
}
Next in the MSP430 project the interface is used in multiple objects. This is one example of multiple implementations, they all give the same error.
#include "Interface.h"
class Derived : public ::NS::Interface
{
public:
// Overriding virtual functions with implementations in cpp file.
void advance() override;
// The problematic function
void advance(const uint32_t N) override;
private:
uint32_t index;
};
The cpp file:
#include "Derived.h"
Derived::advance()
{
++index;
}
Derived::advance(const uint32_t N)
{
index += N;
}
Now inspecting the code for any "funny" characters like Greek question marks did not yield any result. I tried replacing the text, typing it again etc to no result
Commenting out the functions advance(const uint32_t N) resolves the problem so it is not something else in the file.
What could cause this problem?
The problem was indeed as #Clifford mentioned. N was already defined somewhere in the MSP430 code. Renaming Derived::advance(const uint32_t N) to Derived::advance(const uint32_t N_bytes) solves the problem.

Why does inlining my accessors break my code?

I am experiencing a strange issue where attempting to inline the accessors for my "Person" class causes the code to fail to compile.
The following code will compile and run successfully (Using Visual Studio 2012):
Person.h
#pragma once
#include <string>
using namespace std;
class Person
{
public:
Person(string name, int age = 0);
~Person(void);
// Accessors
string name(void) const;
int age (void) const;
private:
string m_name;
int m_age;
};
Person.cpp
#include "stdafx.h"
#include "Person.h"
Person::Person(string name, int age) :
m_name(name),
m_age (age )
{}
Person::~Person(void) {}
string Person::name(void) const
{
return m_name;
}
int Person::age(void) const
{
return m_age;
}
header_test.cpp
#include "stdafx.h"
#include <iostream>
#include "Person.h"
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
Person p("Joe");
cout << p.name() << endl;
return 0;
}
If I change my accessors to be defined as inline functions the code breaks.
Inlining the accessors in Person.h
// Accessors
inline string name(void) const;
inline int age (void) const;
Inlining the accessors in Person.cpp
inline string Person::name(void) const
{
return m_name;
}
inline int Person::age(void) const
{
return m_age;
}
Doing this produces the following errors:
1>header_test.obj : error LNK2019: unresolved external symbol "public: class std::basic_string,class std::allocator > __thiscall Person::name(void)const " (?name#Person##QBE?AV?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std##XZ) referenced in function _wmain
1>fatal error LNK1120: 1 unresolved externals
God that error message is cryptic... Thank you for all of that oh so useful information Microsoft/Visual Studio!
I know the inline keyword is just a "hint" to the compiler and probably has no real value here, but it still shouldn't break the code!
Why is this happening?
I am not a language lawyer, so I can't tell if the compiler behaviour is legitimate or not. Yet, I can explain what is happening.
When you are marking your functions inline, you are not hinting the compiler that it can inline this function. Since over 10 years compilers do not need your hint here. They know when to inline. Instead, what you do, you indicate the function definition to be local for every translation unit it is included in. For this definition should be available.
Effectively what you said is that name() definition should be local for every .cpp file, but you didn't make it available for every .cpp file! I still believe the compiler could give a warning here.
You need to define the function body in the header if you want to use the inline keyword. inline also does more than just give a hint to the compiler: it more or less shuts down the "one definition" rule* about functions being defined once and only once.
Furthermore, if you define class member functions inside the headers, ala
class Foo {
int bar() { return 5; }
};
they get "inlined" by default, so there's no reason to type the keyword out :-)
* Technically not, but for simplicity you can think of it as behaving that way. See the comment below by SergeyA.

g++ 4.2: internal compiler error: in make_thunk, at cp/method.c:129

I asked this question already on http://www.cplusplus.com/forum/general/96128/ but to no avail.
does anybody experienced the same bug with g++ 4.2: internal compiler error: in make_thunk, at cp/method.c:129
I think it is not neccessary to include sample code. The respective code compiles without warnings and errors on several other newer g++ versions, as well as on clang++. It is simply correct and the bug was mentioned in the GCC's bugzilla (even several times, because it seems to recurr often), but no workaround was provided.
Please don't tell also to use a newer g++. I MUST compile it on the g++ shipped with Ubuntu Hardy, so I cannot change the compiler. Main development is done on Ubuntu Precise, but I need to keep it compatible to Hardy.
I have no idea what a thunk should be, I only suspect it has to do with covariants and/or multiple inheritance. Also I have several more similar structured header files, which all compile well, despite the only change is the name is the name of the class and I have no aim, to change that because of a compiler bug on Hardy.
Another fact is, it happens at include time.
In file included from /home/heiko/hgl/src/compiler/compilerprojectfactory.cpp:18:
/home/heiko/hgl/src/compiler/compilertype.h: In instantiation of 'HGL::Compiler::CompilerType<HGL::Vector2D, HGL::Compiler::CompilerBase>':
/home/heiko/hgl/src/compiler/compilervector2d.h:23: instantiated from here
/home/heiko/hgl/src/compiler/compilertype.h:22: internal compiler error: in make_thunk, at cp/method.c:129
Please submit a full bug report,
with preprocessed source if appropriate.
See <URL:http://gcc.gnu.org/bugs.html> for instructions.
For Debian GNU/Linux specific bug reporting instructions,
see <URL:file:///usr/share/doc/gcc-4.2/README.Bug
EDIT: Here the header which causes the bug:
#include "compilertype.h"
#include "vector2d.h"
namespace HGL {
class Vector2D;
namespace Compiler {
/**
#author Heiko Schäfer <heiko#rangun.de>
*/
class _LOCAL Vector2D : public Compiler::CompilerType<HGL::Vector2D> {
DISALLOW_COPY_AND_ASSIGN(Vector2D)
public:
Vector2D(float x, float y, int line);
using IType::operator=;
virtual operator HGL::Vector2D &() const throw(InvalidExpressionException);
protected:
virtual ~Vector2D();
void append(ISerializeable::BUFFER *dest, const HGL::IType *type) const;
};
}
}
Here the template:
#include "compilerbase.h"
#include "iproject.h"
#include "util.h"
namespace HGL {
namespace Compiler {
const IProject::VSTRUCT minReq = { HGL_MINREQ_MAJOR, HGL_MINREQ_MAJOR, HGL_MINREQ_MAJOR };
template<class Type, class Base = CompilerBase>
class _LOCAL CompilerType : public Type, public Base {
DISALLOW_COPY_AND_ASSIGN(CompilerType)
public:
using IType::operator=;
template<class Param>
inline CompilerType(const Param &p, bool b, int line,
const IProject::VSTRUCT &vs = IProject::VSTRUCT()) :
Type(p), Base(line, b) {
init(vs);
}
template<class Param>
inline CompilerType(const Param &p, int line,
const IProject::VSTRUCT &vs = IProject::VSTRUCT()) : Type(p), Base(line) {
init(vs);
}
inline CompilerType(bool b, int line, const IProject::VSTRUCT &vs = IProject::VSTRUCT())
: Type(), Base(line, b) {
init(vs);
}
template<class Param1, class Param2>
inline CompilerType(const Param1 &p1, const Param2 &p2, int line,
const IProject::VSTRUCT &vs = IProject::VSTRUCT()) :
Type(p1, p2), Base(line) {
init(vs);
}
template<class Param1, class Param2>
inline CompilerType(const Param1 &p1, const Param2 &p2, bool b, int line,
const IProject::VSTRUCT &vs = IProject::VSTRUCT()) : Type(p1, p2),
Base(line, b) {
init(vs);
}
inline CompilerType(int line,
const IProject::VSTRUCT &vs = IProject::VSTRUCT()) : Type(), Base(line) {
init(vs);
}
inline virtual void append(ISerializeable::BUFFER *dest, const IType *type) const {
Base::append(dest, type);
}
protected:
inline virtual ~CompilerType() {}
inline virtual void init(const IProject::VSTRUCT &vs) {
const_cast<IProject::VSTRUCT &>(vs) = std::max(vs, minReq);
CompilerBase::setMinRequiredVersion(vs, Type::getSerialID());
}
};
}
}
RESOLVED!
After digging in g++ 4.2's source code I found out that it needs to now about all types in the complete tree. g++ > 4.2 apparently doesn't need this.
So, the error was in a related class which had a template member with a forwarded specialization. I just included the header instead of forwarding and g++ 4.2 was happy.
Otherwise it is really a non-nice bug not to give an error, but this useless message.
A thunk or trampoline is a piece of code that is added in some implementations of dynamic dispatch to adapt the interface of the base virtual function with respect to the final overrider being used. As you mentioned it is commonly needed to adapt the this pointer in multiple/virtual inheritance (for bases listed after the first non-empty one) and to adapt the resulting pointer/reference with covariant return types.
The error indicates that it is a compiler bug. If you have to use that particular compiler you will need to work around the issue, and that will involve changing your design. You can try to limit the use of multiple/virtual inheritance, reorder the bases in the list or try to play around until you manage to get the compiler to digest that code somehow. If it is a problem when generating the adapter for a covariant return type, consider removing the covariant return and provide an overload (with a different name) that will return the covariant type (i.e. replace covariant return with a non-virtual function returning the most derived type and a virtual function that calls the previous and returns a reference to the base).
Other than those generic hints, without seeing the code you have and the implementation of the compiler there is little else to say.

undefined reference to `typeinfo and 'vtable

i'm currently working on a program that employs the user of virtual functions. I am using only one virtual function and have come across what seems to be a common problem with a common solution which I have tried but unfortunately to no success.
I originally had virtual void calcArea(); in BasicShape.h without any definition or designation as a pure virtual function. I changed it and added {} at the end (as suggested on another thread with a similar problem) but I still get the following error:
I input:
g++ BasicShape.h BasicShape.cpp circle.h circle.cpp Rectangle.h Rectangle.cpp driver.cpp -o Lab4
And then I get:
/tmp/ccf1Y4Br.o: In function `BasicShape::BasicShape()': circle.cpp:(.text._ZN10BasicShapeC2Ev[_ZN10BasicShapeC5Ev]+0xf): undefined reference to `vtable for BasicShape'
/tmp/ccf1Y4Br.o:(.rodata._ZTI6circle[_ZTI6circle]+0x10): undefined reference to `typeinfo for BasicShape'
/tmp/ccc7gjtH.o:(.rodata._ZTI9Rectangle[_ZTI9Rectangle]+0x10): undefined reference to `typeinfo for BasicShape'
collect2: error: ld returned 1 exit status
Any ideas?
This is the implementation file BasicShape.h:
#ifndef BASICSHAPE_H
#define BASICSHAPE_H
class BasicShape
{
protected:
double area;
public:
double getArea() const;
virtual void calcArea();
};
#endif
The accompanying BasicShape.cpp file:
#include "BasicShape.h"
double BasicShape::getArea() const
{
return area;
}
void BasicShape::calcArea()
{
}
circle.h:
#include "BasicShape.h"
#ifndef CIRCLE_H
#define CIRCLE_H
class circle : public BasicShape
{
private:
long centerX;
long centerY;
double radius;
public:
circle(long, long, double);
long getCenterX() const;
long getCenterY() const;
virtual void calcArea();
};
#endif
circle.cpp:
#include "circle.h"
// constructor
circle::circle(long userIn, long userIn2, double userIn3)
{
centerX = userIn;
centerY = userIn2;
radius = userIn3;
calcArea();
}
// accesors
long circle::getCenterX() const
{
return centerX;
}
long circle::getCenterY() const
{
return centerY;
}
// virtual function
void circle::calcArea()
{
area = (3.14159 * radius * radius);
}
Rectangle.h
#include "BasicShape.h"
#ifndef RECTANGLE_H
#define RECTANGLE_H
class Rectangle : public BasicShape
{
private:
long width;
long length;
public:
Rectangle(long, long);
long getWidth() const;
long getLength() const;
virtual void calcArea();
};
#endif
Rectangle.cpp:
#include "Rectangle.h"
// constructor
Rectangle::Rectangle(long userIn, long userIn2)
{
width = userIn;
length = userIn2;
calcArea();
}
// accessors
long Rectangle::getWidth() const
{
return width;
}
long Rectangle::getLength() const
{
return length;
}
void Rectangle::calcArea()
{
area = (length * width);
}
The driver program is incomplete, but irrelevant to my problem anyway (at least I think so).
#include <cassert>
#include <iostream>
#include "BasicShape.h"
#include "Rectangle.h"
#include "circle.h"
using namespace std;
int main()
{
cout << "Testing the functionality and efficiency of the circle class...\n";
// declare circle object and test accessors and area computation
circle objCircle(8,8,4);
assert(objCircle.getCenterX() == 8);
assert(objCircle.getCenterY() == 8);
assert(objCircle.getArea() == 50.26544);
cout << "Circle object testing completed successfully\n";
cout << "Testing the functionality and efficiency of the Rectangle class...\n";
// declare rectangle object and test accessors and area computation
//Rectangle objRec();
return 0;
}
Actually, as it was pointed out, you have not to compile headers. (Although you can, it is irrelevant here --- gcc will generate precompiled headers).
And more interesting: your example perfectly works here, GCC 4.6.3.
Also, sidenote: calcArea shouldn't be public
You should not tryo to compile the headers:
g++ BasicShape.cpp circle.cpp Rectangle.cpp driver.cpp -o Lab4
Your compiler needs at least one translation unit where a virtual member is defined outside the class definition for each polymorphic class. It will instantiate some internal data for the class (virtual function table, polymorphic typeinfo) only if there is such a translation unit.
(Disclaimer: At least that was the case when I last used it, long ago)
You could either use an out-of-class definition for the BasicShape::calcArea function or add a virtual (optionally even pure virtual) destructor to BasicShape and define it out-of-class. The best place would probably be the BasicShape.cppfile.
BTW: As others have pointed out, you typically should not pass header files as separate translation units to the compiler. This will do no harm (other than inflate your compilation time), but also no good.
Ok, so apparently this all seems to be a compiler issue. This entire time I was using gedit as a text editor and g++ as a compiler, but when I switched over to code blocks it was working just fine.