Linker refers to, supposedly, undefined reference to vtable - c++11

I am trying to use an abstract class to represent a common base for subtypes. However, it (the linker it seems) keeps moaning about vtables and undefined references no matter what I do. Judging by the error messages, the problem must be related to the destructors in some way. Wierdldy enough, it keeps talking about a
"undefined reference to 'AbstractBase::~AbstractBase()'"
in child.cpp which makes no sense.
Like last time, I can't actually show my code, so here is an example that in essence does the same thing:
First the abstract class, "AbstractBase.h":
#ifndef ABSTRACTBASE
#define ABSTRACTBASE
class AbstractBase
{
public:
virtual ~AbstractBase() = 0;
}
#endif
The child that uses the abstractbase, "child.h":
#ifndef CHILD
#define CHILD
class child : public AbstractBase
{
public:
~child() override;
}
#endif
The implementation in "child.cpp":
#include "child.h"
child::~child()
Obviously there are far more functions, but in essence that's how my real class's destructors look.
After scouring the web for ways of using abstract classes in C++, I am about to give up. As far as I can tell from those sources, this is the way to do it. You declare your abstracts class's destructor virtual, so any call to it will include the child. And the child's destructor is simply marked override. There shouldn't be anything else to it.
Have I missed something truly fundamental here?
PS: added MCVE:
class AbstractBase
{
public:
virtual ~AbstractBase() = 0;
};
class child : public AbstractBase
{
public:
void dostuff()
{
//stuff
}
~child() override
{}
}
int main (argc, char *argv[])
{
child* ptr = new child();
ptr->dostuff();
}
I should add that the errors I now get are not entirely identical, while the original ones look like this:
undefined reference to 'vtable for AbstractBase': In function
AbstractBase:~AbstractBase()': Undefined reference to 'vtable for
AbstractBase': Undefined reference to 'typeinfo for AbstractBase':
Collect2:error:ld returned 1 exit status

You need to define a destructor for every class, otherwise you cannot destroy objects of that class (which includes member objects and base sub-objects):
class AbstractBase
{
public:
virtual ~AbstractBase() = default;
}; // ^^^^^^^^^^^
Some alternative formulations:
User-defined:
struct AbstractBase {
virtual ~AbstractBase() {}
};
Pure-virtual, but defined:
struct AbstractBase {
virtual ~AbstractBase() = 0;
};
AbstractBase::~AbstractBase() = default;
This has the benefit of leaving the class abstract even if you have no other virtual member functions.
Combine the two:
struct AbstractBase {
virtual ~AbstractBase() = 0;
};
AbstractBase::~AbstractBase() {}

I thank you all for your assistance. I eventually stumbled upon a solution.
Apperently, having regular virtual functions in the abstract class causes these issues. I recreated both the fix and the error in my MCVE, observe:
Nonfunctional code:
class AbstractBase
{
public:
virtual void idiot();
virtual ~AbstractBase() = 0;
};
AbstractBase::~AbstractBase()=default;
class child : public AbstractBase
{
public:
void dostuff()
{
//stuff
}
void idiot() override
{
}
~child() override
{
}
};
int main(int argc, char *argv[])
{
child* ptr = new child();
ptr->dostuff();
}
Functional code:
class AbstractBase
{
public:
//virtual void idiot();
virtual ~AbstractBase() = 0;
};
AbstractBase::~AbstractBase()=default;
class child : public AbstractBase
{
public:
void dostuff()
{
//stuff
}
/*void idiot() override
{
}*/
~child() override
{
}
};
int main(int argc, char *argv[])
{
child* ptr = new child();
ptr->dostuff();
}
Notice the only change I made, was commenting out the virtual function idiot, and it's implementation in child.
From my point of view, this is illogical. That extra function should not cause problems.
Alternatively, and this is the true solution, one can make all virtual functions pure. This solves the problem.
I can only guess at what's going on here, it would seem it looks for the implementation of the non-pure functions in a AbstractBase.cpp, which ofcourse doesn't exist. The result is the talk about undefined references to vtables and typeinfo for said AbstractBase, it is right in stating that the virtual functions are indeed undefined. But it shouldn't care, the class is abstract.
My conclusion would be, provided this is intended functionality, that you do need to declare all functions pure if you are to use abstract classes in c++, even though logic dictates it would be unnecessary. At any rate, if it is indeed intended, then the compiler should warn the user. The current errormessages are completely useless.

Related

std::function and friend function

In this example, I have a pointer of function (std::function) as an attribute of my class. So I can associate any function of the form void myFunction(void) to my class.
#include <iostream>
#include <functional>
class Example{
private:
int variable=4;
public:
std::function<void(void)> myNonMemberFunction;
Example(void){
}
Example(std::function<void(void)> MyNonMemberFunction){
myNonMemberFunction=MyNonMemberFunction;
}
};
void PrintPlop(){
std::cout<<"plop"<<std::endl;
}
int main() {
Example example(PrintPlop);
example.myNonMemberFunction();
}
Now, I want to do the same but with a function which has accessed to the class attribute like a friend function or a class-member function. How can I do this?
So you want any function you pass to the constructor become a friend?
In the strict sense it is impossible, because the access level (friend or not) is a compile-time issue, and which value is passed to the constructor, generally speaking, is determined only in run-time.
So you either declare all the relevant functions as friends (why not just make them methods in this case?) or pass the private members to them as additional parameters. Like this:
class Example{
private:
int variable=4;
std::function<void(int)> myNonMemberFunction;
public:
Example(void){
}
Example(std::function<void(int)> MyNonMemberFunction){
myNonMemberFunction=MyNonMemberFunction;
}
void callMyNonMemberFunction() {
myNonMemberFunction(variable);
}
};
void PrintPlop(int v){
std::cout<<"plop"<< v << std::endl;
}
int main() {
Example example(PrintPlop);
example.callMyNonMemberFunction();
}

Object Factory registration of template class hierarchy

I implemented a general object factory following the guidelines of Andrei Alexandrescu's book Modern C++ Design, so I can define a class hierarchy like this (I will write the code in the most simplified way, avoiding implementation details or memory allocation/deallocation issues; I'm aware of these things and I would like to focus the discussion on the main issue):
// File "base.h"
#include <string>
#include "singleton.h"
#include "object_factory.h"
class Base;
using SingletonBaseFactory = Singleton
<
ObjectFactory
<
Base, // Abstract product type
std::string, // Identifier type
Base* (*)() // Concrete product creator type
>
>;
class Base {
// Define the interface (virtual functions, virtual dtor)
public:
// Wrap the Factory method
static Base* Factory(const std::string& ID) {
return SingletonBaseFactory::Instance().Factory(ID);
}
};
// File "derived_1.h"
#include "base.h"
class Derived_1 : public Base { /* ... */ };
// File "derived_2.h"
#include "base.h"
class Derived_2 : public Base { /* ... */ };
and register each derived class within an anonymous namespace in the corresponding implementation file:
// File "derived_1.cpp"
#include "derived_1.h"
namespace {
Base* CreateDerived_1() {
return new Derived_1;
}
const bool registered = SingletonBaseFactory::Instance().Register("Derived_1", CreateDerived_1);
}
// Same for Derived_2 in file "derived_2.cpp"
Therefore, an user that wants to use this hierarchy in his code has just to invoke the Base::Factory method with a proper identifier:
// File main.cpp
#include"base.h"
int main(){
Base* pb = Base::Factory("Derived_1");
// Do stuff with pb
return 0;
}
Now, suppose I have a template class hierarchy, say:
// File "baset.h"
#include <string>
#include "singleton.h"
#include "object_factory.h"
template<class T>
class BaseT;
template<class T>
using SingletonBaseTFactory = Singleton
<
ObjectFactory
<
BaseT<T>, // Abstract product type
std::string, // Identifier type
BaseT<T>* (*)() // Concrete product creator type
>
>;
template<class T>
class BaseT {
/*Define the interface*/
public:
BaseT Factory(const std::string& ID) {
return SingletonBaseTFactory<T>::Instance().Factory(ID);
}
};
// File "derivedt_1.h"
#include "baset.h"
template<class T>
class DerivedT_1 : public BaseT<T> { /* ... */ };
In this case the registration is an user responsibility for each type T he wants to use, before using the class hierarchy:
// File main.cpp
#include "baset.h"
#include "derivedt_1.h"
bool register_derived_1_int = SingletonBaseTFactory<int>::Instance().Register("Derived_1", [](){ return new DerivedT_1<int>; });
int main() {
BaseT<int>* pb = BaseT<int>::Factory("Derived_1");
return 0;
}
Keeping in mind that the ID of each derived template class is the same for every type T, would it make sense to delegate the registration responsibility to the developer of each derived class (rather than the user) even in the templated case?
If so, is there a workaround to achieve it?
EDIT:
I found this work https://www.artima.com/cppsource/subscription_problem.html which addresses the object factory registration problem in the templated case.
However, the registration of the derived classes is still a responsibility of whoever knows the type(s) the derived class can be instantiated with.
Typically, the class developer does not have such a knowledge - the user does have it.
So, again, is there any method to dismiss the user from the responsibility of registering the derived class?

CRTP to avoid code duplication : can't assignment Base=Derived by value

I have classes Base, Derived1, Derived2, etc.
It is compilable (below).
class Base{ };
class Derived1 : public Base{
public: Derived1* operator->() { return this; }
public: void f1(){}
};
class Derived2 : public Base{
public: Derived2* operator->() { return this; }
};
class Derived3 : public Derived2{
public: Derived3* operator->() { return this; }
};
int main(){//test case (my objective is to make all these work)
Derived1 d1; d1->f1();
Base b=d1; //non harmful object slicing
Derived3 d3;
Derived2 d2=d3;
}
Edit: I believe it is a non-harmful object slicing, and I think it is unrelated to the question.
Then, I want the operator->() to be inside Base, so I don't have to implement in all DerivedX class.
This is my attempt so far, using CRTP. It is uncompilable at # :-
class Base{ };
template<class T1,class T2>class Helper{
public: T2* operator->() { return static_cast<T2*>(this); }
};
class Derived1 : public Helper<Base,Derived1>{
public: void f1(){}
};
class Derived2 : public Helper<Base,Derived2>{ };
class Derived3 : public Helper<Derived2,Derived3>{ };
int main(){
Derived1 d1; d1->f1();
Base b=d1; //#
Derived3 d3;
Derived2 d2=d3;
}
I have read these two promising links (below), and do little progress (above) :-
operator= and functions that are not inherited in C++?
Inheritance in curiously recurring template pattern polymorphic copy (C++)
Wiki states that casting Derive to Base is quite impossible for CRTP, so I feel that there might be no solution using CRTP.
Question:
How to move the operator-> to some kind of a base class to avoid code duplication?
(with or without CRTP are both OK)
Is there any solution using CRTP? In other words, is CRTP not suitable for this job?
I am new to CRTP (just play with it today). Sorry if it is duplicated.
Put aside the slicing of your objects, your example works just fine if you define your helper as:
template<class T1, class T2>
class Helper: public T1 {
public:
T2* operator->() {
return static_cast<T2*>(this);
}
};
That is:
Derive from T1 as if in a pure mixin based approach
Use T2 as if in a pure CRTP approach
If you consider the declaration of Derived1:
class Derived1: public Helper<Base, Derived1>;
It goes without saying that now Base b = d1; works, for Derived1 inherits directly from Base.

C++ class member callback and external library

I would like to solve this issue about class member function callback.
Imagine you have a function from an external library (which cannot be modified!) like this:
void fortranFunction(int n, void udf(double*) );
I would like to pass as the udf function above a function member of an existing class. Please look at the following code:
// External function (tipically from a fortran library)
void fortranFunction(int n, void udf(double*) )
{
// do something
}
// User Defined Function (UDF)
void myUDF(double* a)
{
// do something
}
// Class containing the User Defined Function (UDF)
class myClass
{
public:
void classUDF(double* a)
{
// do something...
};
};
int main()
{
int n=1;
// The UDF to be supplied is myUDF
fortranFunction(n, myUDF);
// The UDF is the classUDF member function of a myClass object
myClass myClassObj;
fortranFunction(n, myClassObj.classUDF); // ERROR!!
}
The last line of the code above results in a compilation error, because you cannot declare the classUDF member function as a static function.
Do you know if it is possible to solve this issue?
Probably Boost libraries could help me, but I do not know how (please consider that fortranFunction cannot be modified because is from an external library).
Thanks a lot!
Alberto
I don't understand, why can't you declare classUDF as static like this
class myClass {
public:
static void classUDF(double *a) {
...
}
};
and then pass it like
fortranFunction(n, myClass::classUDF);
You might try that solution (a little bit hacky, but I think, it should work for you):
void fortranFunction(int n, void udf(double*))
{
double d = static_cast<double>(n);
udf(&d);
}
class myClass {
public:
void classUDF(double* a) {
}
};
#ifdef _MSC_VER
#define THREADLOCALSTATIC __declspec(thread) static
#define THREADLOCAL
#else
#define THREADLOCALSTATIC static ___thread
#define THREADLOCAL ___thread
#endif
struct _trampolinebase {
THREADLOCALSTATIC _trampolinebase* current_trampoline;
};
THREADLOCAL _trampolinebase* _trampolinebase::current_trampoline = 0;
#undef THREADLOCAL
#undef THREADLOCALSTATIC
template<class CBRET, class CBARG1, class T>
struct _trampoline1 : _trampolinebase
{
typedef CBRET (T::*CALLBACKFN)(CBARG1);
_trampoline1(T& target, CALLBACKFN& callback)
: callback_(callback)
, target_(target)
{
assert(current_trampoline == 0);
current_trampoline = this;
}
static CBRET callback(CBARG1 a1) {
_trampoline1* this_ = static_cast<_trampoline1*>(current_trampoline);
current_trampoline = 0;
return this_->trampoline(a1);
}
private:
CBRET trampoline(CBARG1 a1) {
return (target_.*callback_)(a1);
}
CALLBACKFN& callback_;
T& target_;
};
template<class FRET, class FARG1, class CBRET, class CBARG1, class T, class F>
FRET call1_1(T& target, CBRET (T::*callback)(CBARG1), F& fortranfunction, FARG1 a)
{
typedef typename _trampoline1<CBRET, CBARG1, T> trampoline;
trampoline t(target, callback);
return fortranFunction(a, trampoline::callback);
}
int main()
{
int n=1;
myClass myClassObj;
call1_1<void,int,void,double*>(myClassObj, &myClass::classUDF, fortranFunction, 1);
}
With the 'threadlocal' stuff, this will work in multithreaded calls, too. You may omit that, if you don't use a multithreaded environment. It also works with recursive calls (e.g. if the callback calls another fortran function).
This solution works only for one single argument plus callback for the fortran function and one single argument in the callback function itself, but you should be able to extend it easily. This is also, why I called it 'call1_1' (fortran function with 1 argument, callbackfunction with 1 argument). FRET is the return type of the fortran function, FARG1 the type of the first argument (int in this case). CBRET and CBARG are the same for the callback function.
Before the fortran function is actually called, the target object is stored within a global (thread-local) variable. The fortran function calls a static callback function, which finally calls your member function.
I invented the trampolinebase to instantiate the static member, I could also have used a global variable for that (but for some reason, I don't like global variables too much) ;-)

Passing non static delegate property function as parameter in C++ / CLI

I make a interface class in C++ for voice recognition, i´m using the Julius API. http://julius.sourceforge.jp/en_index.php?q=index-en.html.
Well, my class has some events, these events will be triggered by the Julius API.
The Julius API has the function call callback_add with this signature:
int callback_add (Recog *recog, int code, void(*func)(Recog *recog, void *data), void data)
I using some 'proxy' functions to Invoke the events and passing this functions to callback_add.
If the property event is static, it works fine, but if is a non static, inside the proxy function the property not be recognized.
The difficult is because I have to use the callback_add function and can't modify this.
Here is a summary of the class with 2 events (static and non-static)
Header
#ifndef FALAENGINE_H_
#define FALAENGINE_H_
#pragma once
extern "C"{
#include <julius/julius.h>
}
namespace FalaAPI {
public ref class FalaEngine
{
public:
FalaEngine();
~FalaEngine();
// Events
delegate void OnRecognizedDele(FalaAPI::RecoResult^ result);
static property OnRecognizedDele^ OnRecognized;
delegate void OnEngineStartDele();
property OnEngineStartDele^ OnEngineStart;
private:
Recog *recog;
Jconf *jconf;
};
}
#endif /* FALAENGINE_H_*/
Source
#include "stdafx.h"
using System::String;
using System::Console;
#include "FalaEngine.h"
#include <windows.h>
namespace FalaAPI{
void StartOnEngineStart()(Recog *recog, void * dummy){
if(FalaEngine::OnEngineStart->GetInvocationList()->Length > 0)
FalaEngine::OnEngineStart->Invoke();
}
void StartOnRecognized()(Recog *recog, void * dummy){
if(FalaEngine::OnRecognized->GetInvocationList()->Length > 0)
FalaEngine::OnRecognized->Invoke();
}
FalaEngine::FalaEngine(){
recog = j_recog_new();
jconf = j_jconf_new();
//Julius callback Functions
callback_add(recog, CALLBACK_EVENT_PROCESS_ONLINE, StartOnEngineStart, NULL);
callback_add(recog, CALLBACK_RESULT, StartOnRecognized, NULL);
}
}
The problem occurs inside StartOnEngineStart function:
error C2227: left of '->GetInvocationList' must point to class/struct/union/generic type
A non-static member exists separately in each instance. You haven't specified which instance contains the delegate you want to inspect, you've only specified a class (and there may be many instances).
Try using the dummy parameter to pass your instance. But be careful, because the garbage collector will move objects around unless you have pinned them, so simply passing the address will not work. You need to create and pass a GCHandle instead. (Be careful not to leak the GCHandle, or your object will never be released)
Something like this should be effective:
ref class FalaEngine;
struct EngineHandle
{
gcroot<FalaEngine^> handle;
EngineHandle(FalaEngine^ engine) : handle(engine) {}
};
public ref class FalaEngine
{
clr_scoped_ptr<EngineHandle> callback_ptr;
public:
FalaEngine();
~FalaEngine();
// Events
delegate void OnRecognizedDele(FalaAPI::RecoResult^ result);
property OnRecognizedDele^ OnRecognized;
delegate void OnEngineStartDele();
property OnEngineStartDele^ OnEngineStart;
private:
Recog *recog;
Jconf *jconf;
};
void StartOnEngineStart(Recog *recog, void * dummy)
{
FalaEngine^ that = static_cast<EngineHandle*>(dummy)->handle;
that->OnEngineStart(); // C++/CLI already checks if the invocation list is empty
}
void StartOnRecognized(Recog *recog, void * dummy)
{
FalaEngine^ that = static_cast<EngineHandle*>(dummy)->handle;
that->OnRecognized(recog->get_result());
}
FalaEngine::FalaEngine()
: callback_ptr(new EngineHandle(this))
{
recog = j_recog_new();
jconf = j_jconf_new();
//Julius callback Functions
callback_add(recog, CALLBACK_EVENT_PROCESS_ONLINE, StartOnEngineStart, callback_ptr.get());
callback_add(recog, CALLBACK_RESULT, StartOnRecognized, callback_ptr.get());
}
The clr_scoped_ptr class is here. There are not many license requirements, make sure you follow them though if you use it.

Resources