Undefined Reference to 'vtable for class' - c++

I am implementing a Visitor class in C++ that generates XML output for a parse tree.
When I compile with Clion on Windows the code compiles but when it runs after it outputs what is expected it crashes. The error code is this
Process finished with exit code -1073741819 (0xC0000005)
When I try to compile using gcc (without Clion) I get the error message
Undefined Reference to 'vtable for PrintXMLVisitor'.
My code is the following. I have distilled it down to the least amount the produces the error
ASTNode.h
#ifndef MINILANG_ASTNODE_H
#define MINILANG_ASTNODE_H
#include <memory>
class Visitor;
class ASTNode {
public:
virtual void accept(std::shared_ptr<Visitor> visitor) = 0;
};
#endif //MINILANG_ASTNODE_H
ASTTypeNode.h
#ifndef MINILANG_ASTTYPENODE_H
#define MINILANG_ASTTYPENODE_H
#include "ASTNode.h"
class ASTTypeNode: public ASTNode {
public:
enum Type {Real, Int, Bool, String};
ASTTypeNode(Type type);
Type getType() const;
void accept(std::shared_ptr<Visitor> visitor) override;
private:
Type type;
};
#endif //MINILANG_ASTTYPENODE_H
ASTTypeNode.cpp
#include "ASTTypeNode.h"
#include "Visitor.h"
ASTTypeNode::ASTTypeNode(ASTTypeNode::Type type)
: type(type)
{
}
ASTTypeNode::Type ASTTypeNode::getType() const {
return type;
}
void ASTTypeNode::accept(std::shared_ptr<Visitor> visitor) {
visitor->visit(std::shared_ptr<ASTTypeNode>(this));
}
Visitor.h
#ifndef MINILANG_VISITOR_H
#define MINILANG_VISITOR_H
#include <memory>
#include "ASTTypeNode.h"
class Visitor {
public:
virtual void visit(std::shared_ptr<ASTTypeNode> typeNode) = 0;
};
#endif //MINILANG_VISITOR_H
PrintXMLVisitor.h
#ifndef MINILANG_PRINTXMLVISITOR_H
#define MINILANG_PRINTXMLVISITOR_H
#include "Visitor.h"
class PrintXMLVisitor: public Visitor {
public:
void visit(std::shared_ptr<ASTTypeNode> typeNode) override;
};
#endif //MINILANG_PRINTXMLVISITOR_H
PrintXMLVisitor.cpp
#include "PrintXMLVisitor.h"
#include <iostream>
void PrintXMLVisitor::visit(std::shared_ptr<ASTTypeNode> typeNode) {
std::string typeName;
switch(typeNode->getType())
{
case ASTTypeNode::Type::Real:
typeName = "Real";
break;
case ASTTypeNode::Type::Int:
typeName = "Int";
break;
case ASTTypeNode::Type::Bool:
typeName = "Bool";
break;
case ASTTypeNode::Type::String:
typeName = "String";
break;
default:
typeName = "Error";
exit(22);
}
std::cout << "<TypeNode>" << typeName << "</TypeNode>" << std:: endl;
}
main.cpp
#include <iostream>
#include "Lexer.h"
#include "ASTTypeNode.h"
#include "PrintXMLVisitor.h"
int main() {
ASTTypeNode astTypeNode (ASTTypeNode::Type::Int);
astTypeNode.accept(std::make_shared<PrintXMLVisitor>());
return 0;
}

Your crafting a shared pointer that isn't dynamic. Specifically,
void ASTTypeNode::accept(std::shared_ptr<Visitor> visitor) {
visitor->visit(std::shared_ptr<ASTTypeNode>(this)); // <=== HERE
}
The this in that statement refers to:
int main()
{
ASTTypeNode astTypeNode (ASTTypeNode::Type::Int); // <== this object
astTypeNode.accept(std::make_shared<PrintXMLVisitor>());
return 0;
}
Changing toolchains isn't going to fix this problem you have options, the two most obvious being:
Stop using a std::shared_ptr for the visit parameter.
Manage all ASTNodeType instances a requiring being std::shared_ptr managed and share from this using the std:enable_shared_from_this capabilities of the standard library.
The former of these is obvious (or at least it is now), so I'll not discuss it further. The latter is not necessarily trivial, as it mandates any instances of your underlying class that utilize shared_from_this must be managed by std::shared_ptr wrappers. I.e., there are no concrete constructions like you're currently doing in main(). This could have significant impact on your overall code base, so choose this carefully.
An example of how the above would work in your case:
First, change the derivation chain of ASTNodeType to look like this:
class ASTTypeNode
: public ASTNode
, public std::enable_shared_from_this<ASTTypeNode> // ADDED
Next, utilize shared_from_this as follows:
void ASTTypeNode::accept(std::shared_ptr<Visitor> visitor)
{
visitor->visit(shared_from_this()); // HERE
}
And finally, honor the warrant you've made that ASTNodeType instances are shared-ptr managed by doing this:
int main()
{
std::shared_ptr<ASTTypeNode> astTypeNode = std::make_shared<ASTTypeNode>(ASTTypeNode::Type::Int);
astTypeNode->accept(std::make_shared<PrintXMLVisitor>());
return 0;
}
That should work. Read more about the things used in the above code here:
std::enable_shared_from_this
std::enable_shared_from_this::shared_from_this
As I said, all of this is to facilitate using a std::shared_ptr from an object given only a this pointer. If you can remove that requirement in the first place, it may be an easier path to take, and I would consider that first.

Related

C++: Sharing an object between two other objects

There are 1 main class and 3 classes: Main, MLME, MAC and Network.
I would want an MLME object to be created within the MAC object upon calling the constructor of the MAC. Then share the same object to the Network object when calling the Network constructor.
This without making the MLME object global or allocating memory with malloc() or new.
I believe this should be done with references which I don't understand fully. Also there might have to be some initializer-list in Network.cpp? I am more experienced with C than C++ and have tried a lot in order to understand all of this.
This is some of my thoughts of the structure, header and cpp files:
Main.cpp
#include "MAC.h"
#include "Network.h"
int main() {
MAC mac();
Network network(mac);
return 0;
}
Here is the MLME part to be shared:
MLME.h
#ifndef MLME_H_INCLUDED
#define MLME_H_INCLUDED
class MLME {
public:
MLME();
};
#endif
MLME.cpp
#include "MLME.h"
MLME::MLME() {}
The MAC class:
MAC.h
#ifndef MAC_H_INCLUDED
#define MAC_H_INCLUDED
#include "MLME.h"
class MAC {
private:
MLME mlme; // NULLED ?
public:
MAC();
MLME getMLME();
};
#endif
MAC.cpp
#include "MAC.h"
MAC::MAC() {
mlme = MLME:MLME();
}
MLME MAC::getMLME() {
return mlme;
}
The Network class:
Network.h
#ifndef NETWORK_H_INCLUDED
#define NETWORK_H_INCLUDED
#include "MLME.h"
class Network {
private:
MLME& mlme;
public:
Network(MAC mac);
};
#endif
Network.cpp
#include "Network.h"
class MAC;
Network::Network(MAC mac) {
mlme = mac.getMLME();
}
You're close, but:
The Network::Network constructor should take MAC by reference, like so: Network::Network(MAC& mac). Currently you take a copy, which means taking a copy of MLME as well.
In addition, the Network::Network constructor should use an initializer list to initialize mlme. So the full form would be:
Network::Network(MAC& mac) : mlme(mac.getMLME()) {}
MAC::getMLME() should return a reference to MLME: MLME& MAC::getMLME(). Otherwise you return a copy.
The explicit construction of MLME in the MAC constructor is not needed: it is already default-constructed.
You may want to prevent copying of MLME instances by saying MLME(const MLME&) = delete. If it is really a shared resource, you want any changes to go back to the shared instance. Making it impossible to copy MLME instances will prevent you from accidentally making or modifying a copy.
In your main function: MAC mac() does not do what you think it does. Remove the () or you get a "most vexing parse" error.
Main.cpp
int main() {
MAC mac;
Network network(mac);
mac.set(10);
mac.print();
network.print();
mac.set(11);
mac.print();
network.print();
return 0;
}
MLME.h
#ifndef MLME_H_INCLUDED
#define MLME_H_INCLUDED
#include "iostream"
using namespace std;
class MLME {
private:
int i;
public:
MLME();
void print();
void set(int in);
};
#endif
MLME.cpp
#include "MLME.h"
MLME::MLME() {}
void MLME::print() { cout << 'i' << i << endl; }
void MLME::set(int in) {
i = in;
}
MAC.h
#ifndef MAC_H_INCLUDED
#define MAC_H_INCLUDED
#include "MLME.h"
class MAC {
private:
MLME mlme; // NULLED ?
public:
MAC();
MLME& getMLME();
void print();
void set(int in);
};
#endif
MAC.cpp
#include "MAC.h"
MAC::MAC() {
mlme = MLME();
}
MLME& MAC::getMLME() {
return mlme;
}
void MAC::print() {
mlme.print();
}
void MAC::set(int in) {
mlme.set(in);
}
Network.h
#ifndef NETWORK_H_INCLUDED
#define NETWORK_H_INCLUDED
#include "MAC.h"
class Network {
private:
MLME& mlme;
public:
Network(MAC& mac);
void print();
};
#endif
Network.cpp
#include "Network.h"
Network::Network(MAC& mac) : mlme(mac.getMLME()) {}
void Network::print() {
mlme.print();
}
output
i10
i10
i11
i11

Casting to undeclared type

The idea is identical to the generic version of GetComponent() in Unity. But I'm currently stumbling on the following template issue:
template<class T> std::shared_ptr<T> MyClass::GetMyComponent()
{
for (int i = 0; i < _baseTypeList.size(); i++)
{
auto base = _baseTypeList[i];
T* check = dynamic_cast<T*>(base.get());
if (check)
{
return std::static_pointer_cast<T>(base);
}
}
return std::shared_ptr<T>(nullptr);
}
where _baseTypeList is a std::vector<std::shared_pntr{MyBaseType}> types.
In this function, I am iterating over a list of components to find if there is one that matches the type I'm asking for. if there is one, return the component cast to that type. Otherwise return a nullptr.
However, when I call this function from outside code, I get the following error:
error C2680: 'MyType*' : invalid target type for dynamic_cast
where MyType is some class that derives from component.
When I put #include "MyType.h" in the header it compiles just fine but without it it gives this error and doesn't compile.
This means I cannot use it in other classes without modifying the header file this template class resides in, which will be a problem for me.
Is there a way I can achieve simular results without having to #include every single header of the type I pass in the template for?
[EDIT]
For clarity, consider a person using my library, he creates a type
"Foo : MyBaseType" where MyBaseType has a virtual method "Update" that is called every frame.
any instance of class MyBaseType (including Foo) is to be managed by this library, and have update called every frame.
This library thus has a large list of "MyBaseType" objects. But has no knowledge of the actual type they are, just that they derive from "MyBaseType", so it can call Update() on them.
If I need a specific type the library needs to be able to search for it in this list and return it.
I would like this "search" to happen in the library itself, so I do not have to expose the list, and write a new "search" method for every type that derives from "MyBaseType"
[FINAL]
It turned out I messed up the include order in my project.
a minimal example of what I was trying to do would be:
#include <stdio.h>
#include <tchar.h>
#include <iostream>
#include <memory>
#include "vector"
class MyBaseClass
{
virtual void Update(){};
};
class MyLibrary
{
public:
template<class T> std::shared_ptr<T> GetComponent();
std::vector<std::shared_ptr<MyBaseClass>> list;
};
template<class T> std::shared_ptr<T> MyLibrary::GetComponent()
{
static_assert(std::is_base_of<MyBaseClass, T>::value, "T1 is no subclass of ModelComponent");
for (unsigned int i = 0; i < list.size(); i++)
{
auto comp = list[i];
T* check = dynamic_cast<T*>(comp.get());
if (check)
{
return std::static_pointer_cast<T>(comp);
}
}
return std::shared_ptr<T>(nullptr);
}
class MyClass : public MyBaseClass
{
void Update() override;
};
void MyClass::Update()
{
}
int _tmain(int argc, _TCHAR* argv[])
{
MyLibrary lib;
lib.list.push_back(std::make_shared<MyClass>());
auto var = lib.GetComponent<MyClass>();
std::cout << (var ? "var is object" : "var is not") << std::endl;
while (true)
{
}
return 0;
}
which works as expected.
The primary issue was that the compiler gave an error in the "GetMyComponent" function, so I found a usage of it that did everything as suggested.
But it turned out there was a second usage that did not have the definition of "MyClass" before calling it (but didn't give an error, as it was forward declared in its header file).
You don't need the definition of possible T types included into your header. You do need the relevant one defined in the translation unit in which the template is expanded:
// client.cpp
#include <myclass.h>
#include <foo.h> // defines class Foo
void f(MyClass *p)
{
auto c = p->GetMyComponent<Foo>();
c->foobar();
}

Function calls with class members?

Before I present the code which is found at the bottom of this post I would like to talk about the issue and the fix's that I do not desire. Okay basically I've created a GUI from scratch sort of and one requirement I wanted for this was allow components to have their own click executions so if i click a button or tab etc.. It would call Component->Execute(); Well normally you would do something like a switch statement of ids and if that components ID equaled n number then it would perform this action. Well that seemed kinda dumb to me and I thought there has to be a better way. I eventually tried to incorporate a feature in JAVA where you would do like Component.AddActionListener(new ActionListener( public void execute(ActionEvent ae) { })); or something like that and I thought that this feature has to be possible in C++. I eventually came across storing void functions into a variable in which could be executed at any time and modified at any time. However I hadn't noticed an issue and that was this only worked with static functions. So below you'll see my problem. I've patched the problem by using a pointer to SomeClass however this would mean having an individual function call for every class type is there no way to store a function callback to a non-static class member without doing the below strategy? and instead doing a strategy like the commented out code?
//Main.cpp
#include <iostream> //system requires this.
#include "SomeClass.h"
void DoSomething1(void)
{
std::cout << "We Called Static DoSomething1\n";
}
void DoSomething2(void)
{
std::cout << "We Called Static DoSomething2\n";
}
int main()
{
void (*function_call2)(SomeClass*);
void (*function_call)() = DoSomething1; //This works No Problems!
function_call(); //Will Call the DoSomething1(void);
function_call = DoSomething2; //This works No Problems!
function_call(); //Will Call the DoSomething2(void);
SomeClass *some = new SomeClass(); //Create a SomeClass pointer;
function_call = SomeClass::DoSomething3; //Static SomeClass::DoSomething3();
function_call(); //Will Call the SomeClass::DoSomething3(void);
//function_call = some->DoSomething4; //Non-Static SomeClass::DoSomething4 gives an error.
//function_call(); //Not used because of error above.
function_call2 = SomeClass::DoSomething5; //Store the SomeClass::DoSomething(SomeClass* some);
function_call2(some); //Call out SomeClass::DoSomething5 which calls on SomeClass::DoSomething4's non static member.
system("pause");
return 0;
}
//SomeClass.hpp
#pragma once
#include <iostream>
class SomeClass
{
public:
SomeClass();
~SomeClass();
public:
static void DoSomething3(void);
void DoSomething4(void);
static void DoSomething5(SomeClass* some);
};
//SomeClass.cpp
#include "SomeClass.h"
SomeClass::SomeClass(void)
{
}
SomeClass::~SomeClass(void)
{
}
void SomeClass::DoSomething3(void)
{
std::cout << "We Called Static DoSomething3\n";
}
void SomeClass::DoSomething4(void)
{
std::cout << "We Called Non-Static DoSomething4\n";
}
void SomeClass::DoSomething5(SomeClass *some)
{
some->DoSomething4();
}
Secondary Fix for what I'll do not an exact answer I wanted but it meets my needs for now along with allowing additional features which would have become overly complicate had this not existed.
//Component.hpp
#pragma once
#include <iostream>
#include <windows.h>
#include <d3dx9.h>
#include <d3d9.h>
#include "Constants.hpp"
#include "ScreenState.hpp"
#include "ComponentType.hpp"
using namespace std;
class Component
{
static void EMPTY(void) { }
static void EMPTY(int i) { }
public:
Component(void)
{
callback = EMPTY;
callback2 = EMPTY;
callback_id = -1;
}
Component* SetFunction(void (*callback)())
{
this->callback = callback;
return this;
}
Component* SetFunction(void (*callback2)(int), int id)
{
this->callback_id = id;
this->callback2 = callback2;
return this;
}
void execute(void)
{
callback();
callback2(callback_id);
}
}
The syntax for pointers-to-member-functions is as follows:
struct Foo
{
void bar(int, int);
void zip(int, int);
};
Foo x;
void (Foo::*p)(int, int) = &Foo::bar; // pointer
(x.*p)(1, 2); // invocation
p = &Foo::zip;
(x.*p)(3, 4); // invocation
Mind the additional parentheses in the function invocation, which is needed to get the correct operator precedence. The member-dereference operator is .* (and there's also ->* from an instance pointer).

boost::lambda expression fails to compile because of instantiation of abstract template arg. Any explanation and/or work arounds?

I'm in the process of learning boost::lambda and I've managed to create a situation that I can't resolve with what I know so far.
Apparently in the bowels of boost::lambda, the following example causes the attempted instantiation of abstract class AbstractFoo, and prevents the lambda expression from compiling. The problem is that I don't know why it is trying to instantiate it so I cant try to work around it.
Any boost::lambda experts that can:
give me a clue as to why this is happening?
suggest a work around?
Example:
#include <boost/lambda/bind.hpp>
#include <boost/lambda/lambda.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/function.hpp>
struct AbstractFoo
{
typedef boost::shared_ptr<AbstractFoo> Ptr;
virtual int it() const = 0;
};
struct Bar : public AbstractFoo
{
typedef boost::shared_ptr<Bar> Ptr;
virtual int it() const { return 3; }
};
typedef AbstractFoo Foo; // Comment this out
//typedef Bar Foo; // and this in to make this example compilable
int main()
{
namespace bll = boost::lambda;
boost::function< bool (const Foo::Ptr &)> func;
func = (bll::protect(bll::bind( &Foo::it, *bll::_1))(bll::_1) == 3);
return 0;
}
This fails to compile (on gcc 4.4.3, boost 1_40) with a monster template error the important part of which seems to be:
error: cannot declare field
‘boost::tuples::cons<AbstractFoo,boost::tuples::null_type>::head’
to be of abstract type ‘AbstractFoo’
because the following virtual functions are pure within ‘AbstractFoo’:
virtual int AbstractFoo::it() const
As you discovered, you can not do that, because the object needs to be copied, but in this case it can not be instantiated because it contains a pure virtual method. The simplest solution is to pass it using a pointer :
#include <boost/lambda/bind.hpp>
#include <boost/lambda/lambda.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/function.hpp>
#include <iostream>
struct AbstractFoo
{
typedef boost::shared_ptr<AbstractFoo> Ptr;
virtual int it() const = 0;
};
struct Bar : public AbstractFoo
{
typedef boost::shared_ptr<Bar> Ptr;
virtual int it() const { return 3; }
};
typedef AbstractFoo Foo; // Comment this out
//typedef Bar Foo; // and this in to make this example compilable
int main()
{
namespace bll = boost::lambda;
boost::function< bool ( const Foo * )> func;
func = ( bll::protect( bll::bind( &Foo::it, bll::_1 ) )( bll::_1 ) == 3);
//func = bll::bind( &Foo::it, bll::_1 );
Foo::Ptr p( new Bar );
std::cout << std::boolalpha << func( p.get() ) << std::endl;
}
To be more precise, this :
*bll::_1
needs to instantiate and copy object of type AbstractFoo
Riffing off of JVo's answer, the following works around the issue:
func3 = (bll::protect(bll::bind( &Foo::it,
bll::bind( &Foo::Ptr::get,
bll::_1 ))) (bll::_1) == 2);
where
bll::bind( &Foo::Ptr::get, bll::_1)
Pulls out the pointer so that the place holder is not dereffed in line.
From the comments suggesting compiling without error in VS with Boost 1_47 I might guess that the issue has since been fixed in boost, and that it was a sort of bug.

How to create a library that wraps an object with a template function using minimal includes?

The goal of this project is to create a library for distribution. In the past, I used forward declares so I didn't have to distribute a bunch of header files along with the libraries. However, I'm now trying to eliminate code duplication by switching to templates and am running into some issues.
First, a simple example project showing what is currently working:
//LibraryDep1.h
class LibraryDep1
{
public:
LibraryDep1(void) {};
virtual ~LibraryDep1(void) {};
template <typename T>
int TestFunction(T value)
{
std::cout << value << std::endl;
return 0;
}
};
//LibraryInclude.h
class LibraryDep1; //forward declare
class LibraryInclude
{
private:
LibraryDep1* mLibDep1;
public:
LibraryInclude(void);
virtual ~LibraryInclude(void);
int TestFunction(int value);
int TestFunction(std::string value);
};
//LibraryInclude.cpp
#include "LibraryInclude.h"
#include "LibraryDep1.h"
LibraryInclude::LibraryInclude(void)
{
this->mLibDep1 = new LibraryDep1();
}
LibraryInclude::~LibraryInclude(void)
{
delete this->mLibDep1;
}
int LibraryInclude::TestFunction(int value)
{
return this->mLibDep1->TestFunction(value);
}
int LibraryInclude::TestFunction(std::string value)
{
return this->mLibDep1->TestFunction(value);
}
//main.cpp
#include <tchar.h>
#include "LibraryInclude.h"
int _tmain(int argc, _TCHAR* argv[])
{
LibraryInclude inclLibrary;
inclLibrary.TestFunction(77);
inclLibrary.TestFunction("test");
}
This gives the expected output of:
77
test
However, the overloads of LibraryInclude::TestFunction could be replaced with a template function to further reduce code duplication:
//LibraryInclude.h
class LibraryDep1; //forward declare
class LibraryInclude
{
private:
LibraryDep1* mLibDep1;
public:
LibraryInclude(void);
virtual ~LibraryInclude(void);
template <typename T>
int TestFunction(T value) {
return mLibDep1->TestFunction(value);
}
};
The problem now is that I'm using mLibDep1 without including the full implementation giving me an undefined type compilation error. Meaning that I need to #include "LibraryDep1.h" in LibraryInclude.h, thus requiring me to distribute both LibraryInclude.h and LibraryDep1.h with my library. This is a simple example, the real project has many header files that would need to be distributed if I were to switch to using the templated version of LibraryInclude.
My question is, is there any way to avoid having to distribute a bunch of include files with my library and eliminate code duplication? Or, am I better off just overloading for all known types (drastically reducing library flexibility) in the distributed header file and keeping the templates in only the underlying classes?
No. There is currently no way to do what you want. When compiler vendors start implementing the 'export' keyword you'll be in luck. Currently I only know of Comeau doing so. This keyword has been around for years so I wouldn't hold my breath until the rest implement it.
A very limited and ugly solution would be:
//LibraryDep1.h
#pragma once
#include <iostream>
class LibraryDep1
{
public:
LibraryDep1(void) {};
virtual ~LibraryDep1(void) {};
template <typename T>
int TestFunction(T value)
{
std::cout << value << std::endl;
return 0;
}
};
//LibraryInclude.h
#pragma once
class LibraryDep1; //forward declare
class LibraryInclude
{
private:
LibraryDep1* mLibDep1;
public:
LibraryInclude(void);
virtual ~LibraryInclude(void);
template <typename T>
int TestFunction(T value);
};
//LibraryInclude.cpp
#include "LibraryInclude.h"
#include "LibraryDep1.h"
#include <string>
LibraryInclude::LibraryInclude(void)
{
mLibDep1 = new LibraryDep1();
}
LibraryInclude::~LibraryInclude(void)
{
}
// only to save some typing when only forwaring calls
#define LI_TESTFUNCTION( TYPE ) \
template<> \
int LibraryInclude::TestFunction<TYPE>( TYPE value ) {\
return mLibDep1->TestFunction(value); \
}
// the allowed specializations, everything else causes link errors
LI_TESTFUNCTION( int );
LI_TESTFUNCTION( std::string );
Tested this with VC++ 2k8 & g++ 4.3.4 statically linking against LibraryInclude.o