c++ undefined reference to vtable - c++

I'm learning C++. I'm trying to do an exercise where I define several implementations of a pure virtual class with a single function. I'm having trouble linking the class that uses these implementations.
==> BasicMath.h <==
#ifndef BASIC_MATH_H
#define BASIC_MATH_H
#include<string>
#include<vector>
class BasicMath { };
#endif // BASIC_MATH_H
==> Operation.h <==
#ifndef OPERATION
#define OPERATION
#include<string>
#include<vector>
class Operation {
public:
virtual void perform(std::vector<std::string> vec) = 0;
};
#endif // OPERATION
==> Sum.h <==
#ifndef SUM_H
#define SUM_H
#include "Operation.h"
class Sum: public Operation {
public:
void perform(std::vector<std::string> vec);
};
#endif // SUM_H
==> BasicMath.cpp <==
#ifndef BASIC_MATH_C
#define BASIC_MATH_C
#include <string>
#include <vector>
#include <iostream>
#include "BasicMath.h"
#include "Sum.h"
int main(int argc, char* argv[]) {
Sum op;
}
#endif // BASIC_MATH_C
==> Sum.cpp <==
#ifndef SUM_C
#define SUM_C
#include <vector>
#include <string>
#include <iostream>
#include "Sum.h"
void Sum::perform(std::vector<std::string> vec) {
using namespace std;
int total = 0;
cout << "Total: " << total << "\n";
};
#endif // SUM_C
Compilation:
$ g++ -c Sum.cpp
$ g++ -o BasicMath BasicMath.cpp
/tmp/cc1VXjNl.o:BasicMath.cpp:(.text$_ZN3SumC1Ev[Sum::Sum()]+0x16): undefined reference to `vtable for Sum'
collect2: ld returned 1 exit status
I'm 95% sure I'm doing at least one foolish thing here - but my brain is refusing to tell me what.
I have see this question but have not managed to fix my issue.

I Just encountered the same problem, but my problem was that I had not written the destructor code in my .cpp file.
class.h:
class MyClass {
public:
MyClass();
virtual ~MyClass();
};
class.cpp:
MyClass::MyClass() {}
It just gave me the vtable error message, and implementing the (empty) destructor solved the problem.
[Edit] Thus, the corrected class file looks like this:
MyClass::MyClass() {}
MyClass::~MyClass() {}

You're not including the Sum.o object file on your compile&link line (second g++ use).

That error also happens if you forget the = 0 for pure virtual functions
Error:
class Base {
public:
virtual void f();
};
class Derived : public Base {
public:
virtual void f() {}
};
int main() {
Derived d;
Base *b = &d;
(void)b;
}
No error:
class Base {
public:
virtual void f() = 0;
};
This is because without the = 0, C++ does not know that it is a pure virtual function, treats it as a declaration, expecting a later definition.
Tested on g++ 5.2.1.
Tested as of GCC 11.2.0, the error message changed to:
undefined reference to `typeinfo for Base'
command:
g++ -ggdb3 -O0 -std=c++11 -Wall -Wextra -pedantic -o main.out main.cpp

A couple of people have already pointed out the solution to the problem you've seen.
I'll add something rather different. You only need header guards in your headers. You've included them in your source files as well, where they really don't make sense. For example, I've commented out the lines you really don't need (or even want) in sum.cpp:
//#ifndef SUM_C
//#define SUM_C
//
#include <vector>
#include <string>
#include <iostream>
#include "Sum.h"
void Sum::perform(std::vector<std::string> vec) {
using namespace std;
int total = 0;
cout << "Total: " << total << "\n";
};
//#endif // SUM_C
Just FWIW, instead of perform, I'd use operator():
class Operation {
public:
virtual void operator()(std::vector<std::string> vec) = 0;
};
and (obviously) that's also what you'd overload for Sum. To use it, instead of something like:
Sum op;
op.perform();
You'd use something like:
Sum op;
op();
This is particularly convenient when you combine your class with others (e.g., those in the standard library) that invoke operations like functions, whether they're really functions, or "functors" (classes like this, that overload operator() so syntactically they can be used almost like functions).

I normally encounter this error when I accidentally forget the =0 at the end of one of my functions in a pure virtual class.

You're just compiling BasicMath.cpp without Sum.cpp - your linker has no idea about Sum.cpp. You'll need to compile them both together, i.e. Sum.cpp BasicMath.cpp in one go, or you can compile the .cpp files independently and then create the executable by calling g++ with both .o files.

I have met the problem same as yours , and I solved this problem by adding three lines in the CMakeLists.txt , that is:
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)

Related

Troubles separating C++ source file into multiple files

Let me specify exactly what I'm trying to do, I need to split my foo-bar program into five separate files: main, foo.h, foo.cpp, bar.h, bar.cpp. My header files (foo.h and bar.h) are meant to contain the declarations for their corresponding classes, while the c++ files (foo.cpp and bar.cpp) are meant to define the class.
I'm using Visual Studio, and thus far the only file I have showing red flags is my main file. Here is my code thus far, and I will include the errors that are being thrown in my main file:
main.cpp
#include <iostream>
#include "foo.h"
#include "foo.cpp"
#include "bar.h"
#include "bar.cpp"
using namespace std;
int main() {
Bar b(25); /*I am getting a red flag under the 25, stating there is no constructor that can convert int to Bar*/
b.func1(); /*I'm getting a red flag under func1 and func2 stating neither of them are members of Bar*/
b.func2(34);
return 0;}
foo.h
#ifndef foo_h
#define foo_h
#include "foo.cpp"
class Foo {};
#endif
foo.cpp
#ifndef foo_c
#define foo_c
#include "foo.h"
#include "bar.cpp"
private:
int data;
public:
Foo(int d) : data(d) {}
int get_data() { return data; }
virtual void func1() = 0;
virtual int func2(int d) = 0;
#endif
bar.h
#ifndef bar_h
#define bar_h
#include "bar.cpp"
#include "foo.h"
class Bar : public Foo {};
#endif
bar.cpp
#ifndef bar_c
#define bar_c
#include "bar.h"
#include "foo.h"
#include "foo.cpp"
Bar(int d) : Foo(d) {}
void func1() {
cout << "Inside func1\n";
cout << "\tData is " << get_data() << endl;
}
int func2(int d) {
cout << "Inside func2 with " << d << endl;
cout << "\tData is " << get_data() << endl;
return d;
}
#endif
My program worked until I split it up, but now it keeps throwing this message at me when I try to compile it, and there are a couple of red flags in my main code. This is what the console tells me:
No suitable constructor exists to convert int to Bar
func1 is not a member of class Bar
func2 is not a member of class Bar
My question is: What am I doing wrong, and is there a better way to go about what I'm trying to do?
Thank you in advance.
There is more than one misconception manifested in this code. Perhaps it is easier to correct them altogether than to describe and discuss them individually.
Let us start from the bottom of the dependency tree. There at the bottom is a virtual class Foo. Here is its correct declaration.
#ifndef foo_h
#define foo_h
class Foo {
private:
int data;
public:
Foo(int);
int get_data();
virtual void func1() = 0;
virtual int func2(int) = 0;
};
#endif
Note that we include the declarations of all its methods in the header file. However the implementation of the nonvirtual methods is moved out into the foo.cpp file.
#include "foo.h"
Foo::Foo(int d) : data(d) { }
int Foo::get_data() { return data; }
Note that we do not need any special devices to protect from multiple inclusion of the .cpp file because we are not going to include it ever.
Now Foo is the parent of the class Bar that does some real work for us. Once again, all its methods are declared within the class declaration.
#ifndef bar_h
#define bar_h
#include "foo.h"
class Bar : public Foo {
public:
Bar(int);
void func1();
int func2(int);
};
#endif
And its implementation is in the corresponding compilation unit called bar.cpp. When implementing a class method we indicate which class the method belongs to by prepending the class name to the method name, e.g. Bar::func1.
#include "bar.h"
#include "foo.h"
#include <iostream>
Bar::Bar(int d) : Foo(d) {};
using namespace std;
void Bar::func1() {
cout << "Inside func1\n";
cout << "\tData is " << get_data() << endl;
}
int Bar::func2(int d) {
cout << "Inside func2 with " << d << endl;
cout << "\tData is " << get_data() << endl;
return d;
}
Finally we use it in the main.cpp where only a small change is required.
#include <iostream>
#include "foo.h"
#include "bar.h"
using namespace std;
int main() {
Bar b(25);
b.func1();
b.func2(34);
return 0;}
Let's now proceed with building our project. If you were using GCC that would've been easy to describe as a sequence of CLI commands. Since you are using Visual Studio, you would have to perform the corresponding actions through the GUI.
First compile Foo
g++ -c -Wall foo.cpp
Next compile Bar
g++ -c -Wall bar.cpp
Compile main
g++ -c -Wall main.cpp
Now link it all together
g++ -o main foo.o bar.o main.o
Finally run it and voila
Inside func1
Data is 25
Inside func2 with 34
Data is 25
You should never #include .cpp files. Instead, compile each .cpp file into an object file and link them into an executable.
During the preprocessor stage, the compiler takes all of the #included files and treats them as if they were concatenated into one large program. Sometimes, certain files may be #included multiple times. Declarations, in header files, may be repeated, but multiple definitions, from source files, cause errors. (You probably don't have this problem because you used include guards in your source files.)
When creating object files, header files are used by the compiler to check names and types, but the actual definitions are not needed. The definitions that are found are compiled into the object file. The purpose of separate object files is to separate compilation of these definitions into modular units.

CLion checks and extern declaration of a C++ class without default constructor

I have a working class, as example:
// MyClass.h
class MyClass {
public:
explicit MyClass(unsigned char enablePin);
void enable(bool enable);
private:
const unsigned char mEnabePin;
};
// MyClass.cpp
#include "MyClass.h"
#include <gpio.h>
MyClass::MyClass(unsigned char enablePin)
: mEnabePin(enablePin) {
}
void MyClass::enable(bool enable) {
gpio_set(mEnabePin, static_cast<unsigned char>(enable ? 0 : 1));
}
Then I have in another file extern declaration of one instance of this class:
// main.h
extern MyClass myClass;
and of course an actual definition in one .cpp file:
// main.cpp
#include "main.h"
#include <Board.h>
MyClass myClass(Board::Pins::MYCLASS_ENABLE_PIN);
int main() {
// ...
myClass.enable(true);
}
This compiles without warnings with -Wall -Wextra and also works well.
However it seems that CLion 2017.2.1 does not properly get the extern declaration and always complains about:
and offers me these intention actions:
despite the fact that it recognises declaration-definition as it shows red-green arrows as a Go to definition/declaration shortcut.
I could turn off this type of checks, but they belong to very useful set of type checks, that is Function parameter count mismatch which I do not want to turn off.
Have anyone run into the same problem and found a neat workaround?

Why do C++ member functions defined in a class not produce duplicate symbols, whereas they do in C?

C Example
bb.c:
#include "bb.h"
#include <stdio.h>
void bb() {
printf("aa()...\n");
aa();
}
main.c:
#include "aa.h"
#include "bb.h"
int main(int argc, const char** argv) {
aa();
bb();
return 0;
}
aa.h:
#ifndef aa_h
#define aa_h
#include <stdio.h>
void aa() {
printf("aa()...\n");
}
#endif // aa_h
bb.h:
#ifndef bb_h
#define bb_h
#include "aa.h"
void bb();
#endif // bb_h
C Result
Compiled with clang main.c bb.c:
duplicate symbol _aa in:
/var/folders/f2/2w4c0_n519g8cd2k6xv66hc80000gn/T/main-OsFJVB.o
/var/folders/f2/2w4c0_n519g8cd2k6xv66hc80000gn/T/bb-OkcMzn.o
ld: 1 duplicate symbol for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
C++ Example
b.cpp:
#include "b.hpp"
void b::do_something_else() {
std::cout << "b::do_something_else() being called..." << std::endl;
a a;
a.doit();
}
main.cpp:
#include "a.hpp"
#include "b.hpp"
int main() {
a a;
b b;
a.doit();
b.do_something_else();
return 0;
}
a.hpp:
#ifndef a_hpp
#define a_hpp
#include <iostream>
class a{
public:
void doit() {
std::cout << "a::doit() being called..." << std::endl;
}
};
#endif // a_hpp
b.hpp:
#ifndef b_hpp
#define b_hpp
#include "a.hpp"
#include <iostream>
class b{
public:
void do_something_else();
};
#endif // b_hpp
C++ Result
The above compiles fine with clang++ main.cpp b.cpp and the output to the program is:
a::doit() being called...
b::do_something_else() being called...
a::doit() being called...
Questions
Why does the duplicate error not occur with the C++ version?
Does the fact that the function void a::doit() is defined in the header file rather than a source file mean that the compiler will automatically inline the function?
In C++ class methods are not top-level symbols, but are effectively scoped names within their class hierarchy.
This means that you have defined in C++ two doit() methods, a::doit() and b::doit()
In C, you have attempted to define one aa() function twice.
Note that C++ will give an error too if you define the doit() method twice, within the scope of the same class.
#include <iostream>
class a {
public:
void doit() {
std::cout << "hello" << std::endl;
}
void doit() {
std::cout << "goodbye" << std::endl;
}
};
leads to
ed.cpp:11:8: error: ‘void a::doit()’ cannot be overloaded
void doit() {
^
ed.cpp:7:8: error: with ‘void a::doit()’
void doit() {
^
In your C example, aa is defined twice, which violates the "one definition rule". This would be equally true if it were C++.
In your C++ example, a::doit is defined twice, but it is implicitly declared inline. Member functions defined within a class are implicitly inline per [dcl.fct.spec]/3:
A function defined within a class definition is an inline function. ...
inline functions are an exception to the one definition rule (in fact, this is the only meaning of inline required by the standard) per [basic.def.odr]/5.
There can be more than one definition of a ... inline function with external linkage (7.1.2) ... in a program, provided that each definition appears in a different translation unit, and provided the definitions satisfy the following requirements. ...
The requirements essentially boil down to a requirement that the definitions be identical in every translation unit where they appear.
Had you declared aa as inline, similar rules would have applied and your code would have compiled and worked as expected.
Why does the duplicate error not occur with the C++ version?
Because there is no duplication. C++ member functions are scoped by the class they are defined in. b::doit() isn't a duplicate of a::doit().
Does the fact that the function void a::doit() is defined in the header file rather than a source file mean that the compiler will automatically inline the function?
No, but it means it is possible.

Deriving cuda-class from c++ class, in large framework

I have a quite large c++/mpi project in which I want to integrate some cuda-functionality.
I created a sample project (not runnable yet) to illustrate the problem. The comments in between the sources describe the problem.
I have a main.cc:
/*main.cc*/
#include <iostream>
#include "derivedclass.h"
#include "someotherclass.h"
using namespace std;
int main(){
int intstate = 4;
DerivedClass<int> myDerivedClass;
myDerivedClass.setState(intstate);
myDerivedClass.compute();
int result = myDerived.getResult();
SomeOtherClass mySomeOtherClass(result);
mySomeOtherClass.print();
}
which includes some c++ class(es):
/*someotherclass.h*/
#ifndef INTEGRATOR_H_GUARD
#define INTEGRATOR_H_GUARD
class SomeOtherClass{
private:
int someVariable;
public:
SomeotherClass(int someVariable);
void print();
};
#endif
/*someotherclass.cc*/
#include "someotherclass.h"
SomeOtherClass::SomeOtherClass(int someVariable){
this->someVariable = someVariable;
}
SomeOtherClass::print(){
cout << this->someVariable << endl;
}
These c++ parts a quite large and I don't won't to change them.
There is some baseclass:
/*baseclass.h*/
#ifndef BASECLASS_H_GUARD
#define BASECLASS_H_GUARD
class BaseClass{
protected:
int someVariable;
public:
BaseClass(int someVariable);
void compute();
int getResult();
};
#endif
/*baseclass.cc*/
BaseClass::BaseClass(int someVariable){
this->someVariable = someVariable;
}
void BaseClass::compute(){
/* do something*/
}
int BaseClass::getResult(){
return this->someVariable;
}
This base class provides a lot of functionality (too much but not my project so I can't change that).
Some methods are to be parallelized by me. So for me it seems to be the cleanest way to derive the BaseClass with a Class using Cuda:
/*derivedclass.h*/
#ifndef DERIVEDCLASS_H_GUARD
#define DERIVEDCLASS_H_GUARD
#include "baseclass.h"
class DerivedClass: public BaseClass{
public:
DerivedClass(int someVariable);
void compute();
};
#endif
/*derivedclass.cu*/
#include "derivedclass.h"
DerivedClass::DerivedClass(int someVariable):
BaseClass(someVariable);
{
}
void DerivedClass::compute(){
/* do some cuda stuff*/
}
So I have the following questions:
Is it possible to derive a cuda-class from a c++-class
When I try to compile the main.cc class with g++ and the .cu classes with nvcc I get an error when using cuda stuff in the .cu class for example cudamalloc:
./Folder/class.cu:line: Fehler: expected initializer before »cudaMalloc«
When I try to compile the main class with nvcc I get problems with MPI-functionality.
So is it possible to use a cuda-class from a main.cc compiled with g++/mpicc (which seems to be the right way round for me)?
I hope I described my problem understandable and appreciate any help.
From what I can tell from your code, your derived class is just a C++ class that launches CUDA kernels. So it's not really a "CUDA class". So the answer to your question 1. is "yes", you can do that. You just have to put any member functions that launch kernels in .cu files with the kernels they launch.
The error "expected initializer before 'cudaMalloc'" is a weird syntax error. It doesn't really seem to have anything to do with your derived class stuff. I suspect you just have a C++ syntax error.

strange behavior with friend functions -- scope "globalized" when object pointer passed?

Let's say I have a header file a.h and a source file a.cpp. When I try to compile this and call what() from a different file (e.g. main.cpp) which includes a.h:
a.h:
class A {
friend void what();
public:
int index;
};
a.cpp:
#include "a.h"
#include <iostream>
void what() {
std::cout << "what" << std::endl;
}
It fails, as expected (error: 'what' was not declared in this scope). However, when I do the same thing with this:
a.h:
class A {
friend void what(A *thing);
public:
int index;
};
a.cpp:
#include "a.h"
#include <iostream>
void what(A *thing) {
std::cout << thing->index << std::endl;
}
It compiles and runs just fine on g++ 4.4.1 (assuming "index" has been initialized, of course). I don't know much about C++, but I would assume that, by passing the object pointer to the function, the function somehow became available to the global scope (i.e. gets "promoted" in order to be able to "see" an object which previously existed on the same scope as it). I haven't tried this with other kinds of functions yet, but, when using g++ and friend functions, I get this behavior. Is this supposed to happen in C++?
Thanks and sorry if this is a noobish question, my friend Google was failing me.
I compiled your code with g++ 4.5.1 and no error was reported.
I think you have forgotten ; at the end of your class declaration.
Following code works perfectly fine for me (gcc 4.4.5)
a.h
class A {
friend void what();
private:
int index;
};
a.cpp
#include <iostream>
#include "a.h"
using namespace std;
void what()
{
cout << "what" << endl;
}
int main()
{
what();
return 0;
}
UPDATE
You should declare what function in the a.h header file before A class declaration.