problem with inheritance - c++

class OGraph {
public:
OGraph() { }
virtual ~OGraph();
virtual bool is_directed()=0;
};
class OUGraph : public OGraph {
public:
OUGraph() { }
bool is_directed() { return false; }
~OUGraph() {}
};
but when I do this
OUGraph myGraph();
cout << myGraph.is_directed();
I get the following error:
Undefined symbols: "typeinfo for
OGraph", referenced from:
typeinfo for OUGraphin main.o "vtable for OGraph", referenced from:
OGraph::OGraph()in main.o mkdir -p dist/Debug/GNU-MacOSX "OGraph::~OGraph()", referenced from:
g++ -o
dist/Debug/GNU-MacOSX/opengraph
build/Debug/GNU-MacOSX/OGraph.o
build/Debug/GNU-MacOSX/main.o
OUGraph::~OUGraph()in main.o
OUGraph::~OUGraph()in main.o ld: symbol(s) not found collect2: ld
returned 1 exit status make[2]: *
[dist/Debug/GNU-MacOSX/opengraph]
Error 1 make[1]: [.build-conf]
Error 2 make: ** [.build-impl] Error
2
BUILD FAILED (exit value 2, total
time: 568ms)

This:
OUGraph myGraph();
is declaring a function called myGraph that returns a OUGraph. You need to instead have:
OUGraph myGraph;
This declares a variable, as you intend.

It's the same old thing all new C++ people fall for.
OUGraph myGraph();
You've not created a variable called myGraph, you've declared a function called myGraph that returns an OUGraph. Remove the "()".
You also apparently never defined your base's destructor anywhere. Even if it's empty you'll need to define it since you declared it in your class definition.

You have no implementation provided for virtual ~OGraph();. Either provide an implementation, specify it as pure virtual with = 0;, or just get rid of it.
The compiler is expecting to attach type info for the class to the implementation of its first virtual method. Your first virtual method is undefined, so the implementation is never generated, and you get related linking errors.
Additionally, as everyone is saying, you should remove the parentheses from your definition of myGraph.

If you're constructing a new object based using a 'default' constructor, I believe you call it without the empty parenthesis.
So, you would use OUGraph myGraph not OUGraph myGraph()

Related

Issue with ros NodeHandle.subscribe with a class method

I am using ros melodic on Ubuntu18.04 and C++14 and am trying to subscribe to a topic using a callback function in a Derived class. I know this is possible as a base class as seen in the 2.3.2 Class Methods section of the ros wiki, but I am trying to modify that for a derived class. I would like to be able to have multiple Scan_matching derived classes for different algorithms, and for main class to be able to select one. Here is what I have:
class Scan_Matching
{
public:
void get_transform(const sensor_msgs::PointCloud2ConstPtr& cloud_msg);
};
class ICP : public Scan_Matching
{
public:
void get_transform(const sensor_msgs::PointCloud2ConstPtr& cloud_msg);
};
int main(){
...
ScanMatching* scan_matching;
scan_matching = new ICP(...);
ros::Subscriber sub = nh.subscribe(topic, 100, &Scan_Matching::get_transform, scan_matching);
...
}
I am confident this is possible but I am not sure if I am implementing this correctly as I
get a linking error from catkin:
[ 14%] Linking CXX executable /home/mike/documents/autonomous_sim/devel/lib/mike_av_stack/localization
CMakeFiles/mike_av_stack_node.dir/scripts/localization/localization.cpp.o: In function `main':
localization.cpp:(.text.startup+0x718): undefined reference to `Scan_Matching::get_transform(boost::shared_ptr<sensor_msgs::PointCloud2_<std::allocator<void> > const> const&)'
collect2: error: ld returned 1 exit status
mike_av_stack/CMakeFiles/mike_av_stack_node.dir/build.make:392: recipe for target '/home/mike/documents/autonomous_sim/devel/lib/mike_av_stack/localization' failed
make[2]: *** [/home/mike/documents/autonomous_sim/devel/lib/mike_av_stack/localization] Error 1
CMakeFiles/Makefile2:2493: recipe for target 'mike_av_stack/CMakeFiles/mike_av_stack_node.dir/all' failed
make[1]: *** [mike_av_stack/CMakeFiles/mike_av_stack_node.dir/all] Error 2
Makefile:145: recipe for target 'all' failed
make: *** [all] Error 2
Invoking "make -j12 -l12" failed
To me this seems like the subscribe function is sending my get_transform function a parameter that is not the type
const sensor_msgs::PointCloud2ConstPtr& cloud_msg
(or in other words)
const boost::shared_ptr<sensor_msgs::PointCloud2 const>& cloud_msg
but instead the type
boost::shared_ptr<sensor_msgs::PointCloud2_std::allocator<void > const> const&
I tested this by trying the following code which compiles fine.
void callback(const boost::shared_ptr<sensor_msgs::PointCloud2 const>& cloud_msg){
}
int main(){
...
ros::Subscriber sub = nh.subscribe(topic, 100, callback);
...
}
I think it might be because of the derived class and I am calling the incorrect overloaded subscriber function. Can someone help me understand what I am doing wrong, and how to fix? Thank you

Why am I getting a linker error when using this basic inheritance setup?

This is probably a quite simple question, but I don't how to solve it. I have the following setup of my C++ classes:
MappingTechnique.h
struct MappingTechnique {
virtual void processFrame();
};
struct SimpleGreedyMappingTechnique : MappingTechnique {
void processFrame();
};
MappingTechnique.cpp
#include "MappingTechnique.h"
void SimpleGreedyMappingTechnique::processFrame() {
}
Yet, when I build (using CMake) I get the following error:
Linking CXX executable PayloadRegionMapper
Undefined symbols for architecture x86_64:
"typeinfo for MappingTechnique", referenced from:
typeinfo for SimpleGreedyMappingTechnique in MappingTechnique.cpp.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[3]: *** [PayloadRegionMapper] Error 1
make[2]: *** [CMakeFiles/PayloadRegionMapper.dir/all] Error 2
make[1]: *** [CMakeFiles/PayloadRegionMapper.dir/rule] Error 2
make: *** [PayloadRegionMapper] Error 2
I don't get what's the problem here? Why can't I implement the virtual method of the superclass in the subclass? Can anyone help me out on this?
OK, I found the solution myself thanks to #Sneftel's comment noting that I didn't declare it as pure virtual nor did I give it a definition.
After googling what that means, I came up with the following options:
Giving it a definition:
struct MappingTechnique {
virtual void processFrame() {};
};
Making it pure:
struct MappingTechnique {
virtual void processFrame() = 0;
};
I decided for making it pure, only thing to take care of then is that when the abstract class is used (and it is not yet know what actual subclass it will be initialized with), you need to use:
MappingTechnique *mappingTechnique instead of MappingTechnique mappingTechnique
(which is logical when you think about it but might not be that obvious to a C++ novice). Thanks to #Sneftel!

Unable to initialize static map in class [duplicate]

This question already has answers here:
Undefined reference to static class member
(9 answers)
static variable link error [duplicate]
(2 answers)
boost::function static member variable
(1 answer)
Closed 9 years ago.
I am trying to initialise a static map of
map<string, int> in my program as follows:
testApp.h
class testApp(){
public:
void setup();
void update();
void renew();
static map<string, int> _someMap;
};
testApp.cpp
testApp::setup(){
_someMap["something"] = 1;
_someMap["something2"] = 2;
cout<<_someMap["something"]<<"\n";
}
I don't want to use boost for this short use of map and add source dependency for my code. I am not on C++11 and I don't have the constructor here in the program since the class is some framework's class. I am on Xcode and on doing the above in .cpp, I get the following error:
Undefined symbols for architecture i386:
"testApp::mapppp", referenced from:
testApp::setup() in testApp.o
ld: symbol(s) not found for architecture i386
clang: error: linker command failed with exit code 1 (use -v to see invocation)
-- >Additionally, let's say my map is private, for which I tried doing this in my class:
...
private:
static someVariable;
static void someFunction();
.cpp
testApp::setup(){
someFunction();
}
Error:
Undefined symbols for architecture i386:
"testApp::_someMap", referenced from:
testApp::someFunction() in testApp.o
ld: symbol(s) not found for architecture i386
clang: error: linker command failed with exit code 1 (use -v to see invocation)
You've declared the variable in the class definition, but it looks like you haven't defined it. Every static variable needs to be defined in exactly one translation unit. So add a definition to your source file:
map<string, int> testMap::_someMap;
If you like (and if you can't use a C++11 initialiser), you could avoid having to call the setup function by initialising the map from the result of a function instead:
map<string, int> make_map() {
map<string, int> map;
map["something"] = 1;
map["something2"] = 2;
return map;
}
map<string, int> testMap::_someMap = make_map();

C++ templates not defined in header / linker error [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why can templates only be implemented in the header file?
I just came across something that I failed to understand.
I had a problem at the linking stage in the following case.
//header file
class A
{
template<class T>
std::weak_ptr<T> GetSomethingFromSomeWhere(const char* Id);
};
//cpp file
template<class T>
std::weak_ptr<T> A:GetSomethingFromSomeWhere(const char* id)
{
//A method with the right stuff inside and the right return statement
...
}
//Another class
class B
{
};
//main.cpp
int main ()
{
A a;
auto pB = a.GetSomethingFromSomeWhere<B>( "id" );
}
This didn't compile, during linking I have something of this kind :
Undefined symbols for architecture x86_64:
"std::__1::weak_ptr A::GetComponentFromName(char const*)", referenced from:
_main in main.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
I fixed it by defining the template method directly in the header file.
Should I always define template method in the header ? Why ?
I am on OSX and use clang++ with XCode if that can be of any help
Thanks
Template definition needs to be visible to the code using it. Otherwise linker errors will be generated.
There are different workarounds for situations like that:
Read This

Undefined symbols for architecture x86_64:

interface:
class rmKeyControl {
static map<char, function<char(char)>> sm_function_list;
public:
static bool addKeyAction(char, function<char(char)>);
};
implementation:
bool rmKeyControl::addKeyAction(char key, function<char(char)> func) {
if (!sm_function_list.count(key)) {
sm_function_list.insert(pair<char, function<char(char)>>(key, func));
return true;
} return false;
}
The full error message is:
Undefined symbols for architecture x86_64:
"control::rmKeyControl::sm_function_list", referenced from:
control::rmKeyControl::addKeyAction(char, std::__1::function) in rm_KeyControl.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
This seems to be a standard linker error for Xcode 4, but it seems to occur for all sorts of reasons, and it never elaborates. This error seems to indicate the presence of binary instructions that don't work on the x86_64 architecture, but that doesn't make sense in this context. Why am I getting this error?
Edit: I forgot to mention that rmKeyControl is in namespace control. I am using namespace control; in the implementation, although you cannot see it.
Static member is just declaration. Define it in the implementation/source file like-
// include interface header and then do -
map<char, function<char(char)>> rmKeyControl::sm_function_list;