Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I've searched many answers but none of them can solve my problem, I'm new to c++, this issue is quite wired to me. Below is a simplified extraction of my code.
TestHeader.h:
#ifndef NAMESPACE_TESTHEADER_H_
#define NAMESPACE_TESTHEADER__H_
namespace Namespace {
class TestHeader {
public:
TestHeader(const std::string& str) : anyString_(str) { }
virtual std::string methodOne(const std::string& param) const;
virtual ~TestHeader() { anyString_.clear(); }
protected:
std::string anyString_;
};
}
#endif //NAMESPACE_TESTHEADER__H_
TestHeader.cpp:
#include "TestHeader.h"
using namespace std;
namespace Namespace {
TestHeader::TestHeader(const std::string& str):anyString_(str) { <do something>; }
std::string TestHeader::methodOne(const std::string& param) const
{
return <A string>;
}
TestHeader::~TestHeader() {
anyString_.clear();
}
}
What I did was simply call this line in any other .cpp in my package:
#include "TestHeader.h"
TestHeader testHeader("whatever");
The build failed by throwing
error: undefined reference to 'vtable for Namespace::TestHeader'
the vtable symbol may be undefined because the class is missing its key function
The most weird thing is: if I comment out virtual std::string methodOne(const std::string& str) const; in header and its implementation in .cpp, OR, if I comment out : anyString_(str) after constructor and anyString_.clear(); in destructor together in header only, the build will succeed.
Firstly You should not define the constructor and destructor twice. It shouldn't be compiling as mentioned by Curious in comments
Second I assume that you want don't the class to be abstract as there is no Runtime polymorphism implemented which is the basic use of Virtual functions.
If you don't want the class TestHeader to be abstract remove the virtual keyword which is referring to Virtual Table.C++ compiler inserts Virtual Table for every class having virtual function or class inherited from the class that has virtual functions.
Better study the use of Virtual keyword and then write the code.
Here are quick links for the same
Link 1
Link 2
Also, I think you need to revisit few concepts from Destructor virtual ~TestHeader() { anyString_.clear(); } does not make any sense. In fact, there is no base class which in turn denies the use of Virtual Destructor which is used in case of Inheritance
Firstly, include #include <string> at the top of your header file. I am guessing the error is because you have not linked the object file produced after compiling TestHeader.cpp with the source file that contains the declaration and initialization for the variable named testHeader
Compile these with the following command and you should see a linker error that complains saying that you have multiple definitions for the constructor
g++ -std=c++14 TestHeader.cpp yourfile.cpp
After you see those errors, remove the multiple definitions, either put all your definitions in the cpp file or only put them in one place and then recompile and link with the above command. The linker error should be gone.
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I am just starting to learn about classes and i am trying to make a very simple code called cat.
In my main, h, and cpp file it says the class "Cat" has no member "speak" looked for a possible solution for awhile now but cant find anything to help.
If i put void Cat::speak() in my h file it corrects the other two, but then it says "Qualified name is not allowed in member deceleration"
//Main
#include <iostream>
#include "Cat.h"
using namespace std;
int main() {
Cat jim;
jim.speak(); //CLASS "CAT" HAS NO MEMBER "SPEAK"
return 0;
}
//cat.h
#pragma once
#ifndef CAT_H_
#define CAT_H_
class Cat {
public:
void::speak(); //THE GLOBAL SCOPE HAS NO SPEAK
};
#endif /*CAT_H_*/
//cat.cpp
#include <iostream>
#include "Cat.h"
using namespace std;
void Cat::speak() { //CLASS "CAT" HAS NO MEMBER "SPEAK"
cout << "Meow!" << endl;
}
void::speak(); //THE GLOBAL SCOPE HAS NO SPEAK
It's interpreting this as void ::speak() where leading an identifier (a name) with :: indicates to C++, "Look in the global scope of all names". :: is the "scope resolution operator"
In the header file, you should just use void speak(); since C++ sees it inside your class declaration and hence knows it's part of the class.
How did it even try to compile this line: void::speak();?
What did you even mean by it? Method speak() inside void namespace? but void is a reserved typename. Moreover, why is it inside the class then?
As I can guess, you were trying to use void speak(); instead.
void::speak()
I figured I would chime in on this answer. But the above line is your problem. Essentially, what you have asked the program to do is look in the scope of the void namespace. However, void is a reserved typename and to my knowledge, does not have a function named speak() in it.
This is the one of the problems with using namespace std. Usually, when you are using something from the standard library, take string for example, you will say, "I need to declare a string here, from the standard library. std::string hello, is a perfectly good example that states, "string belongs in the standard libraries scope." using namespace std is bad practice and you go fumbling around trying things like void::speak() which again, is asking to grab it from void's namespace.
That being said, in classes, the header file is commonly used to declare functions in which you will use later. In the cpp file, you are simply saying, I have a class Cat and from the scope of Cat I will be using the function speak(). So speak() belongs to the class Cat and is in the scope of Cat. Which is why in the cpp file, you call void Cat::speak();
So in summary, you header file should be:
class Cat
{
public:
void speak(); // the class has a public function named speak.
};
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
I wrote some code trying to understand the relationship between compiling and linking - and also to see where and if function declarations have to be repeated in source files.
The two files I wrote are:
Person.cpp:
#include <string>
class Person {
public:
Person(std::string name) {
(*this).name = name;
};
std::string getName() {
return name;
};
std::string name;
};
and the file
PersonMain.cpp:
#include <iostream>
class Person {
public:
Person(std::string);
std::string getName();
std::string name;
};
int main(){
Person* charlie = new Person("Charlie");
std::cout << "Hi, my name is " << charlie->getName();
}
I repeat the Class Person and Class Person function declarations (not the definitions) in the PersonMain.cpp.
I now compile and link the two files using the gcc C++ Compiler:
g++ *.cpp -o runthis.exe
I then get the following error message:
PersonMain.cpp:(.text+0xfe): undefined reference to
Person::Person(std::basic_string<char,
std::char_traits<char>,std::allocator<char> >)'
PersonMain.cpp:(.text+0x13c): undefined reference to
Person::getName()' collect2.exe: error: ld returned 1 exit status
It seems the Person Class methods are not found when linking. Why is that? How can I heal this?
ADDENDUM:
I repeated the declaration of Person in PersonMain.cpp explicitly, and didn't but the redeclaration into a header file as would be done normally. So I've done the preprocessor step here already. This faq suggests that:
[The Preprocessor] works on one C++ source file at a time by replacing
include directives with the content of the respective files (which is usually just declarations)[...]
and later on:
[The Linker] links all the object files by replacing the references to
undefined symbols with the correct addresses. Each of these symbols
can be defined in other object files or in libraries.
I add this remark becaue #engf-010 said that a Compilation Unit that has code that isn't actually used in that compilation unit is not compiled, even if it is needed in other compilation units. enf-010 suggests that I put the definition and declaration into the header file, but the faq article says that only the declarations should go there, the definitions can be elsewhere.
Usually one splits declarations and definitions into .h and .cpp files respectively.
Your code would look something like this:
person.h - declarations:
#include <string>
class Person {
public:
Person(std::string n);
std::string getName() const;
std::string name;
};
person.cpp - implementation:
#include <string>
#include "person.h"
Person::Person(const char* n) : name(n) { }
std::string Person::getName () const { return name; }
and personmain.cpp - where you use your class Person:
#include <iostream>
#include "person.h"
int main()
{
Person* charlie = new Person("Charlie");
std::cout << "Hi, my name is " << charlie->getName ();
}
Like #engf mentioned, essentially, what you got in your code is double definition of Person and no implementation. You can't easily define Person in main file and implement Person::Person() somewhere else (and you should not), in another translation unit (i.e., in person.cpp), without letting the compiler know what you implement. You can't forward-declare Person and use it in personmain.cpp like this:
class Person;
...
Person* charlie = new Person("whatever");
because compiler should know complete type to emit code constructing the Person-object. You can't have two definitions of Person. You can't implement members of Person without definitions, accessible to all users of your code. So, what you left with is the scheme like this above.
To elaborate a bit more on compilation and linking, very roughly, when compiler sees a reference to symbol not defined locally in the same translation unit, it puts appropriate record into object file. When this object file is passed to the linker (possibly, along with a bunch of other object files and libraries), linker should resolve such records to symbols (functions, variables etc.) found somewhere in input object files or libraries. If it succeeds in that, it combines all the referenced code into single image. In your case the linker failed to resolve referenced symbol Person::Person for constructor. Probably this is not bad Q&A to start.
what you've got is a definition in one source file and a declaration in the other source file.
When the source file containing the definition is compiled ,the compiler comes to the conclusion that there isn't any 'real' code to generate ,because you didn't use the class.
So you end up with an empty object file.
You can define a class in a source file but if you don't use that class in that file it is tossed away as not being used.
If you use that class in other source files (through it's declaration) the compiler generates code for member accesses ,but those are not found during linking.
I am creating a new abstract class in C++/CLI and have run into a strange error. There are many questions similar to this one but none of the answers could help me.
In this new class, I get the following error:
error LNK2020: unresolved token (06000002) Foo::execute
This is the h-file:
#pragma once
using namespace System::IO::Ports;
using namespace System;
public ref class Foo
{
protected:
SerialPort^ port;
public:
Foo(SerialPort^ sp);
virtual array<Byte>^ execute();
};
This is the cpp-file:
#include "StdAfx.h"
#include "Foo.h"
Foo::Foo(SerialPort^ sp)
{
this->port = sp;
}
Note that when I comment out the virtual array<Byte>^ execute(); line, everything compiles perfectly. Also, when I remove the virtual modifier and add an implementation of execute() in the cpp-file, it works as well.
You already gave the answer yourself:
Also, when I remove the virtual modifier and add an implementation of execute() in the cpp-file, it works as well.
You declared the method execute in the header, but it's implementation is missing. That's exactly what the linker error is telling you.
In this case the declaration as virtual does not matter.
If you want to create an abstract class, you can find further details in numerous articles online (e.g. Wikibooks: Abstract Classes)
You have to either implement the method or remove the declaration from the header. (virtual keyword doesn't matter in this case)
Please, ask a question, if you have any.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What is an undefined reference/unresolved external symbol error and how do I fix it?
I'm relatively new to C++ (as you can probably tell by the question) and I've hit a problem. I have two files: Drives.h and Drives.cpp
Drives.h
#pragma once
enum MountMode
{
User,
System,
Both,
Auto
};
class Drive
{
public:
Drive(void);
~Drive(void);
BOOL Mount(MountMode mode);
VOID Unmount(void);
BOOL IsConnected(void);
static char* DeviceName;
static char* DrivePath;
};
class Drives
{
public:
Drives(void);
~Drives(void);
};
and my Drives.cpp:
#include "stdafx.h"
#include "Drives.h"
Drives::Drives(void)
{
Drive USB0; //Error happening here
}
Drives::~Drives(void)
{
}
The error is saying that the Drives class constructor, destructor and IsConnected() are all unresolved externals. I'm not sure what I'm missing since I set this class up like the one on cplusplus.com
Thanks in advance
As the error message says, you have not implemented the constructor and destructor of Drive:
Drive::Drive(void) {
...
}
Drive::~Drive(void) {
...
}
Creating a local variable of class type (as you do in Drive USB0;) will invoke that class' constructor, and the destructor will be invoked at the end of the variable's scope; hence the error.
You should implement the other functions of Drive too - declaring a function in a class declaration is essentially a promise that the function will be implemented somewhere.
Yes, those methods have been declared in the Drive class in your header file, but you haven't actually created a body for these methods.
You must either create a body inline in your header file, create a body in a CPP file, or make sure you are linking with an existing file that defines these methods. Otherwise, the error is right, these methods have not been defined.
An Unresolved External Symbol error usually means you have provided a declaration of a function but not its definition.
In your case, since you declared Drive(void) and ~Drive(void) the compiler removes its defaults and expects your definitions to exist, which they don't, so it throws an error.
As a side note: using void in place of empty parenthesis to mean "This function takes no arguments" is a C-Style definition and should not be used.
Also,do not use #pragma once as a substitute for include guards. It is a Microsoft-Specific construct and is not compatible with other compilers. Use actual include guards instead:
#ifndef CLASS_NAME_H
#define CLASS_NAME_H
//CODE HERE
#endif
In the following code you declare two classes(Drive and Drives), but you provide the implementation only for one (Drives)
#pragma once
enum MountMode
{
User,
System,
Both,
Auto
};
class Drive
{
public:
Drive(void);
~Drive(void);
BOOL Mount(MountMode mode);
VOID Unmount(void);
BOOL IsConnected(void);
static char* DeviceName;
static char* DrivePath;
};
class Drives
{
public:
Drives(void);
~Drives(void);
};
To get rid of the error message, you must include an implementation for Drive's class methods. On way to extend your Drives.cpp so that your code may work looks like this:
#include "stdafx.h"
#include "Drives.h"
//Drive class constructor
Drive::Drive(void)
{
//Add initialization code here. For example:
DeviceName = "Name";
DrivePath = "";
}
//Drive class destructor
Drive::~Drive(void)
{
}
//Also add the implementation for Mount
BOOL Drive::Mount(MountMode mode)
{
//implementation for Mount. For example:
return FALSE;
}
//Also add the implementation for Mount
VOID Drive::Unmount()
{
//implementation for Unmount
}
//Also add the implementation for Mount
BOOL Drive::IsConnected()
{
//implementation for IsConnected.For example:
return FALSE;
}
//Drives class constructor
Drives::Drives(void)
{
Drive USB0; //Error happening here
}
//Drives class destructor
Drives::~Drives(void)
{
}
It is also possible if you copy paste-d the code, that you also have the implementation for the Drive class but you save it in another .cpp file, like Drive.cpp. In that case you should either copy all the implementation methods from the other Drive.cpp file to Drives.cpp. Or you should move the declaration of Drive class from Drives.h to Drive.h. In that case you will have clear separation for classes in different files, which is good, but you will have to include Drive.h in the Drives.h file.
I'm setting up a C++ project, on Ubuntu x64, using Eclipse-CDT. I'm basically doing a hello world and linking to a commerical 3rd party library.
I've included the header files, linked to their libraries, but I still get linker errors. Are there some possible problems here other than the obvious (e.g. I am 99% sure I'm linking to the correct library).
Is there a way to confirm the static libraries I am linking to are 64bit?
Is there a way to confirm that the library has the class (and methods) I am expecting it to have?
Eclipse says:
Building target: LinkProblem
Invoking: GCC C++ Linker
g++ -L/home/notroot/workspace/somelib-3/somelib/target/bin -o"LinkProblem" ./src/LinkProblem.o -lsomelib1 -lpthread -lsomelib2 -lsomelib3
./src/LinkProblem.o: In function `main':
/home/notroot/workspace/LinkProblem/Debug/../src/LinkProblem.cpp:17: undefined reference to `SomeClass::close()'
./src/LinkProblem.o: In function `SomeOtherClass':
/home/notroot/workspace/somelib-3/somelib/include/sql/somefile.h:148: undefined reference to `SomeClass::SomeClass()'
/home/notroot/workspace/somelib-3/somelib/include/sql/somefile.h:148: undefined reference to `vtable for SomeOtherClass'
/home/notroot/workspace/somelib-3/somelib/include/sql/somefile.h:151: undefined reference to `SomeClass::~SomeClass()'
./src/LinkProblem.o: In function `~SomeOtherClass':
/home/notroot/workspace/somelib-3/somelib/include/sql/somefile.h:140: undefined reference to `vtable for SomeOtherClass'
/home/notroot/workspace/somelib-3/somelib/include/sql/somefile.h:140: undefined reference to `SomeClass::~SomeClass()'
/home/notroot/workspace/somelib-3/somelib/include/sql/somefile.h:140: undefined reference to `SomeClass::~SomeClass()'
collect2: ld returned 1 exit status
make: *** [LinkProblem] Error 1
This linker error usually (in my experience) means that you've overridden a virtual function in a child class with a declaration, but haven't given a definition for the method. For example:
class Base
{
virtual void f() = 0;
}
class Derived : public Base
{
void f();
}
But you haven't given the definition of f. When you use the class, you get the linker error. Much like a normal linker error, it's because the compiler knew what you were talking about, but the linker couldn't find the definition. It's just got a very difficult to understand message.
Assuming those methods are in one of the libs it looks like an ordering problem.
When linking libraries into an executable they are done in the order they are declared.
Also the linker will only take the methods/functions required to resolve currently outstanding dependencies. If a subsequent library then uses methods/functions that were not originally required by the objects you will have missing dependencies.
How it works:
Take all the object files and combine them into an executable
Resolve any dependencies among object files.
For-each library in order:
Check unresolved dependencies and see if the lib resolves them.
If so load required part into the executable.
Example:
Objects requires:
Open
Close
BatchRead
BatchWrite
Lib 1 provides:
Open
Close
read
write
Lib 2 provides
BatchRead (but uses lib1:read)
BatchWrite (but uses lib1:write)
If linked like this:
gcc -o plop plop.o -l1 -l2
Then the linker will fail to resolve the read and write symbols.
But if I link the application like this:
gcc -o plop plop.o -l2 -l1
Then it will link correctly. As l2 resolves the BatchRead and BatchWrite dependencies but also adds two new ones (read and write). When we link with l1 next all four dependencies are resolved.
Qt C++ will show this error when you change a class such that it now inherits from QObject (ie so that it can now use signals/slots). Running qmake -r will call moc and fix this problem.
If you are working with others via some sort of version control, you will want to make some change to your .pro file (ie add/remove a blank line). When everyone else gets your changes and runs make, make will see that the .pro file has changed and automatically run qmake. This will save your teammates from repeating your frustration.
The problem for me turned out to be pretty obscure. My class looked like this:
//-----------------------------------------
// libbase.h
class base {
public:
base() { }
virtual ~base() { }
virtual int foo() { return 0; }
};
//-----------------------------------------
//-----------------------------------------
// libbase.cpp
#include "libbase.h"
//-----------------------------------------
//-----------------------------------------
// main.h
class derived : public base {
public:
virtual int foo() ;
};
//-----------------------------------------
//-----------------------------------------
// main.cpp
int main () {
derived d;
}
//-----------------------------------------
The problem is in the linker. My header file went in a library somewhere, but all the virtual functions were declared 'inline' in the class declaration. Since there was no code using the virtual functions (yet), the compiler or linker neglected to put actual function bodies in place. It also failed to create the vtable.
In my main code where I derived from this class, the linker tried to connect my class to the base class and his vtable. But the vtable had been discarded.
The solution was to declare at least one of the virtual functions' bodies outside the class declaration, like this:
//-----------------------------------------
// libbase.h
class base {
public:
base() { }
virtual ~base() ; //-- No longer declared 'inline'
virtual int foo() { return 0; }
};
//-----------------------------------------
//-----------------------------------------
// libbase.cpp
#include "libbase.h"
base::~base()
{
}
//-----------------------------------------
In regards to problems with Qt4, I couldn't use the qmake moc option mentioned above. But that wasn't the problem anyway. I had the following code in the class definition:
class ScreenWidget : public QGLWidget
{
Q_OBJECT // must include this if you use Qt signals/slots
...
};
I had to remove the line "Q_OBJECT" because I had no signals or slots defined.
I had this error message. The problem was that I declared a virtual destructor in the header fileļ¼ but the virtual functions' body was actually not implemented.
This error will also occur when we simply declare a virtual function without any definition in the base class.
For example:
class Base
{
virtual void method1(); // throws undefined reference error.
}
Change the above declaration to the below one, it will work fine.
class Base
{
virtual void method1()
{
}
}
In my case the problem occured when i forgot to add the =0 on one function in my pure virtual class. It was fixed when the =0 was added. The same as for Frank above.
class ISettings
{
public:
virtual ~ISettings() {};
virtual void OKFunction() =0;
virtual void ProblemFunction(); // missing =0
};
class Settings : ISettings
{
virtual ~Settings() {};
void OKFunction();
void ProblemFunction();
};
void Settings::OKFunction()
{
//stuff
}
void Settings::ProblemFunction()
{
//stuff
}
I stumbled across the issue now, too. The application defined a pure virtual interface class and a user-defined class provided through a shared lib was supposed to implement the interface. When linking the application, the linker complained that the shared lib would not provide vtable and type_info for the base class, nor could they be found anywhere else.
Turned out that I simply forgot to make one of the interface's methods pure virtual (i.e. omitted the " = 0" at the end of the declaration. Very rudimentary, still easy to overlook and puzzling if you can't connect the linker diagnostic to the root cause.
I had this error message when trying "hello world" like things with Qt. The problems went away by correctly running the qt moc (meta object compiler) and compiling+including these moc-generated files correctly.
If you have a base class with pure virtual function, make sure your base class constructor and destructor has body otherwise linker fails.
I put this for future visitors:
if you are receiving the error on creating an Exception object, then the cause of it probably is a lack of definition for what() virtual function.